Python: как установить тайм-аут при получении данных в SocketServer.TCPServer

Я прочитал довольно много вещей, и это все еще ускользает от меня. Я знаю, как это сделать при использовании сырых сокетов. Следующее работает просто отлично, время ожидания через 1 секунду, если данные не получены:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((HOST, PORT))
sock.listen(1)
while 1:
    conn, addr = sock.accept()
    data = ''
    conn.settimeout(1)
    try:
        while 1:
            chunk = conn.recv(1024)
            data += chunk
            if not chunk:
                break
        print 'Read: %s' % data
        conn.send(data.upper())
    except (socket.timeout, socket.error, Exception) as e:
        print(str(e))
    finally:
        conn.close()
        print 'Done'

Но при попытке что-то подобное при использовании SocketServer.TCPServer с SocketServer.BaseRequestHandler (не с SocketServer.StreamRequestHandler где я знаю, как установить тайм-аут) кажется, не так тривиально. Я не нашел способа установить тайм-аут для получения данных. Рассмотрим этот фрагмент (не полный код):

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        data = ''
        while 1:
            chunk = self.request.recv(1024)
            data += chunk
            if not chunk:
                break

if __name__ == "__main__":
    HOST, PORT = "0.0.0.0", 9987
    SocketServer.TCPServer.allow_reuse_address = True
    server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)
    server.serve_forever()

Предположим, клиент отправляет только 10 байтов. Цикл while выполняется один раз, чанк не пуст, поэтому выполняется self.request.recv() еще раз, но у клиента больше нет данных для отправки и recv() блоков на неопределенный срок...

Я знаю, что могу реализовать небольшой протокол, проверить завершающие строки / символы, проверить длину сообщения и т. Д., Но я действительно хочу реализовать тайм-аут, а также для непредвиденных обстоятельств (например, клиент "исчезает").

Я хотел бы установить, а также обновить время ожидания, т. Е. Сбрасывать время ожидания после каждого chunk, необходимый для медленных клиентов (хотя это второстепенная проблема на данный момент).

заранее спасибо

2 ответа

Вы можете сделать то же самое с SocketServer.BaseRequestHandler.request.settimeout() как вы сделали с сырым сокетом.

например:

class MyTCPHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        self.request.settimeout(1)
        ...

В этом случае self.request.recv() будет завершен, если это займет более 1 секунды.

class MyTCPHandler(SocketServer.BaseRequestHandler):
timeout=5
...

... вызовет исключение (которое будет обслуживать serve_forever()) и завершит соединение, если пройдет 5 секунд без получения данных после вызова recv(). Будьте осторожны, хотя; он также отключит ваше соединение, если вы отправляете данные более чем на 5 секунд.

Это может быть специфично для Python 3, но это работает для меня.

Другие вопросы по тегам