TCP服务器关闭连接

6 投票
4 回答
8243 浏览
提问于 2025-04-16 16:27

我有这段代码

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

    def handle(self):
        _data = self.request.recv(1024)

        Utils.log("Received from %s: %s" % (self.client_address, _data))

用下面的方式调用它

kamcon_server = ThreadedTCPServer((HOST, 3011), ThreadedTCPRequestHandler)

server_thread = threading.Thread(target = kamcon_server.serve_forever)
server_thread.setDaemon(True)
server_thread.start()

我可以连接到主机,服务器也能发送数据,但当客户端向服务器发送信息时,连接就会自动关闭。为什么会这样呢?谢谢。

4 个回答

1

handle() 方法是在建立新的 TCP 连接时被调用的,而不是每次有数据可用时都调用。你应该在这个方法里处理整个 TCP 会话的所有通信。

因为你只读取了一块数据,所以当 handle() 方法返回时,连接就会关闭。

2

试试这个代码,它可以让多个连接同时使用同一个端口,而且在客户端关闭之前,不会关闭这个连接:

import SocketServer
import socket, threading

class MyTCPHandler(SocketServer.BaseRequestHandler):
        BUFFER_SIZE = 4096
        def handle(self):
                while 1:
                        #get input with wait if no data
                        data = self.request.recv(self.BUFFER_SIZE)
                        #suspect many more data (try to get all - without stop if no data)
                        if (len(data)==self.BUFFER_SIZE):
                                while 1:
                                        try: #error means no more data
                                                data += self.request.recv(self.BUFFER_SIZE, socket.MSG_DONTWAIT)
                                        except:
                                                break
                        #no data found exit loop (posible closed socket)
                        if (data == ""): break

                        #processing input
                        print "%s (%s) wrote: %s" % (self.client_address[0], threading.currentThread().getName(), data.strip())

if __name__ == "__main__":
        HOST, PORT = "localhost", 9999
        server = SocketServer.ThreadingTCPServer((HOST, PORT), MyTCPHandler)
        server.serve_forever()

你也可以用 ForkingTCPServer 来替代 ThreadingTCPServer。

13

你的 handle() 方法每次连接只调用了 recv() 一次。如果你想处理来自客户端的多个消息,就需要使用循环。你还应该考虑一下你的协议,这样你才能处理超过1024字节的请求/响应消息(比如解析 _data,判断是否收到完整的消息,缓存部分请求等等)。

举个例子:

def handle(self):
    close = 0
    while not close:
        _data = self.request.recv(1024)
        if not _data:
            # EOF, client closed, just return
            return
        Utils.log("Received from %s: %s" % (self.client_address, _data))
        self.request.send('got %d bytes\r\n' % len(_data))
        if 'quit' in _data:
            close = 1

客户端会话:

% telnet localhost 3011
hi
got 4 bytes
bye
got 5 bytes
telnet> quit

撰写回答