2016-10-13 8 views
1

Я пишу псевдо-клиент приложение в питоне, требование к которым относятся:HTTP-сервер с активными соединениями TCP в питоне

  1. Он должен обрабатывать HTTP-запросы.
  2. Соединения между клиентом и сервером ожидают ответ-запрос, то есть базовое соединение TCP остается в живых после того, как ответ был отправлен клиенту.
  3. Сервер должен иметь возможность отправлять данные конкретному клиенту, для которого у него уже есть открытое соединение.

Я смотрел на скрученный и python TCPServer/BaseHTTPServer, но они не совсем соответствуют счету. Как я вижу это, у меня есть два варианта:

  1. Начните с реализации сервера HTTP и переопределите мой путь до управления подключением.
  2. Имейте простой сервер сокетов, который будет управлять соединениями и передавать данные между сервером «http» и клиентом.

Неужели кто-нибудь занялся подобной проблемой? Любые идеи о других подходах или какой из них будет лучшим вариантом?

Спасибо!

EDIT 1 Я не могу использовать HTTP 2 или сетевые сокеты; HTTP < 2 над TCP является жестким требованием.

ответ

0

Я закончил переопределять методы в http.server.HTTPServer, это было меньше работы, чем ожидалось, и все это из стандартных пакетов.

В зависимости от вашей ситуации нижняя часть может в конечном итоге быть более вовлеченной, например. используя более структурированное представление сеанса и т. д. Затем вам следует, вероятно, рассмотреть более разработанные рамки, например twisted.

Основные моменты:

  • Используйте ThreadingMixIn - как соединения долговечны, отдельный поток-обработчик будет необходимо для того, чтобы более чем одно соединение одновременно.
  • Обратите внимание, что если вы используете BaseHTTPRequestHandler, соединение закрывается после каждого ответа, если нет заголовка Connection: keep-alive или вы устанавливаете self.close_connection = False на запрос КАЖДЫЙ.

Во всяком случае, фрагмент кода, чтобы вы начали:

from http.server import HTTPServer, BaseHTTPRequestHandler 
from socketserver import ThreadingMixIn 

class MyHandler(BaseHTTPRequestHandler): 

    # Implement do_GET, do_POST, etc. 

    def handle_one_request(self): 
     super(MyHandler, self).handle_one_request() 
     self.close_connection = some_condition() 
     if self.close_connection: 
     # Remove the session from the server as it will be closed after this 
     # method returns 
     self.server.sessions.pop(self.client_address) 

class MyServer(ThreadingMixIn, HTTPServer): 
    def __init__(self, addr_port, handler_class): 
     super(MyServer, self).__init__(addr_port, handler_class) 
     self.sessions = {} # e.g. (addr, port) -> client socket 

    def get_request(self): 
     """Just call the super's method and cache the client socket""" 
     client_socket, client_addr = super(MyServer, self).get_request() 
     self.sessions[client_addr] = client_socket 
     return (client_socket, client_addr) 

    # You may also want to add the following 
    def server_close(self): 
     """Close any leftover connections.""" 
     super(MyServer, self).server_close() 
     for _, sock in self.sessions.items(): 
     try: 
      sock.shutdown(socket.SHUT_WR) 
     except socket.error: 
      pass 
     sock.close() 
1

Поскольку вы не можете использовать веб-порты или http/2, и вам требуется возможность передавать данные с сервера клиенту, тогда длительный опрос, вероятно, лучший вариант.

См. Nevow, at https://github.com/twisted/nevow, для одной возможной реализации длинного опроса через модуль athena.

 Смежные вопросы

  • Нет связанных вопросов^_^