我读过很多东西,但我仍然无法理解。我知道如何在使用原始套接字时做到这一点。以下操作很好,如果没有接收到数据,则在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循环运行一次,chunk不为空,因此再次执行self.request.recv()
,但客户端没有更多的数据可发送,并无限期地执行recv()块。。。
我知道我可以实现一个小协议,检查终止字符串/字符,检查消息长度等,但我真的想实现一个超时,以及不可预见的情况(例如客户端"消失")。
我想设置并更新一个超时,即在每个chunk
之后重置超时,这是慢速客户端所需要的(尽管目前这是次要问题)。
提前感谢
您可以对SocketServer.BaseRequestHandler.request.settimeout()
执行与原始套接字相同的操作。
例如:
class MyTCPHandler(SocketServer.BaseRequestHandler):
def handle(self):
self.request.settimeout(1)
...
在这种情况下,如果完成时间超过1秒,self.request.recv()
将终止。
class MyTCPHandler(SocketServer.BaseRequestHandler):
timeout=5
...
将引发一个异常(serve_forever()将捕获该异常),并在调用recv()后5秒未收到数据时关闭连接。不过要小心;如果发送数据的时间超过5秒,它也会关闭您的连接。
记住,这可能是Python 3特有的,但它对我有效