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, но это работает для меня.