Python:如何在SocketServer.TCPServer中设置接收数据的超时

时间:2014-02-16 10:49:46

标签: python sockets timeout socketserver

我读了很多东西,这仍然让我感到厌烦。我知道在使用原始套接字时如何做到这一点。以下工作正常,如果没有收到数据,则在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.TCPServerSocketServer.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之后的超时(尽管这是目前的次要问题)。< / p>

提前致谢

2 个答案:

答案 0 :(得分:2)

您可以使用SocketServer.BaseRequestHandler.request.settimeout()执行与使用原始套接字相同的操作。

例如:

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

在这种情况下,如果完成时间超过1秒,self.request.recv()将终止。

答案 1 :(得分:0)

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

...将引发异常(serve_forever()将捕获)并在调用recv()后5秒钟没有接收数据时关闭连接。但要小心;如果您发送数据的时间超过5秒,它也会关闭您的连接。

这可能是Python 3的具体内容,但它适用于我。