Python 的 SocketServer 中的 TCPServer + BaseRequestHandler 是不是在每次调用 handle() 后关闭套接字?

Posted

技术标签:

【中文标题】Python 的 SocketServer 中的 TCPServer + BaseRequestHandler 是不是在每次调用 handle() 后关闭套接字?【英文标题】:Does the TCPServer + BaseRequestHandler in Python's SocketServer close the socket after each call to handle()?Python 的 SocketServer 中的 TCPServer + BaseRequestHandler 是否在每次调用 handle() 后关闭套接字? 【发布时间】:2010-01-14 19:09:21 【问题描述】:

我正在用 Python 编写一个客户端/服务器应用程序,我发现有必要为来自客户端的每个请求建立到服务器的新连接。我的服务器只是从 TCPServer 继承,而我从 BaseRequestHandler 继承来进行处理。我没有在处理程序的任何地方调用 self.request.close() ,但不知何故,服务器似乎挂在我的客户端上。怎么了?

【问题讨论】:

这是在 Unix 还是 Windows 上?可以贴一下客户端的sn-p代码吗? 答案就在代码中……看看BaseHTTPServer.py和SocketServer.py 感谢您的指点。我很想知道答案,而不仅仅是在哪里找到答案。 好的,我阅读了代码。实际上,TCPServer 正在关闭连接。在 BaseServer#handle_request 中,调用了 process_request,它调用了 close_request。在 TCPServer 类中,close_request 调用 self.request.close(),而 self.request 只是用来处理请求的套接字。所以我的问题的答案是“是”。 【参考方案1】:

好的,我阅读了代码(在我的 Mac 上,SocketServer.py 位于 /System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/)。

确实,TCPServer 正在关闭连接。在BaseServer.handle_request 中,调用了process_request,它调用了close_request。在TCPServer类中,close_request调用self.request.close()self.request只是用来处理请求的socket。

所以我的问题的答案是“是”。

【讨论】:

【参考方案2】:
    tcpserver 每次“handle”后都会关闭连接

    对等关闭时,以下代码不起作用

    def handle(self):
        while 1:
        try:
            data = self.request.recv(1024)
            print self.client_address, "sent", data
        except:
            pass
    

    这可能会更好:

    def handle(self):
        while(1):
            try:
                self.data = self.request.recv(1024)
                if not self.data:
                    print "%s close" % self.client_address[0]
                    break
                print "%s wrote:" % self.client_address[0], self.data
            except:
                print "except"
                break
    
      reuseaddr 无效,绑定后为时已晚
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

【讨论】:

【参考方案3】:

根据文档,除非提示这样做,否则 TCPServer 和 BaseRequestHandler 都不会关闭套接字。 handle()finish() 的默认实现什么都不做。

可能会发生一些事情:

您正在关闭套接字本身或包装它的请求,或者在某处调用server_close。 可能已遇到套接字超时,并且您已实现关闭套接字的超时处理程序。 客户端实际上可能正在关闭套接字。代码真的有助于解决这个问题。

然而,我的测试证实了你的结果。从服务器上的handle 返回后,无论是通过 telnet 还是 Python 的 socket 模块连接,您的连接都会显示为被远程主机关闭。在句柄内的循环中处理套接字活动似乎有效:

def handle(self):
    while 1:
        try:
            data = self.request.recv(1024)
            print self.client_address, "sent", data
        except:
            pass

简短的 Google 代码搜索确认这是处理请求的典型方式:1234。老实说,如果我面临SocketServer 提供的抽象与我的期望之间的脱节,我可能会考虑使用许多其他可用于 Python 的网络库。

我用来测试的代码示例:

from SocketServer import BaseRequestHandler, TCPServer

class TestRequestHandler(BaseRequestHandler):
    def handle(self):
        data = self.request.recv(1024)
        print self.client_address, "sent", data
        self.request.send(data)

class TestServer(TCPServer):
    def __init__(self, server_address, handler_class=TestRequestHandler):
        TCPServer.__init__(self, server_address, handler_class)

if __name__ == "__main__":
    import socket

    address = ('localhost', 7734)
    server = TestServer(address)
    server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

【讨论】:

【参考方案4】:

您确定客户端没有挂在服务器上?这有点太模糊,无法真正说明发生了什么,但通常从客户端接收数据的服务器将退出读取连接,不返回任何数据。

【讨论】:

以上是关于Python 的 SocketServer 中的 TCPServer + BaseRequestHandler 是不是在每次调用 handle() 后关闭套接字?的主要内容,如果未能解决你的问题,请参考以下文章

Python2与Python3的区别/网络编程/socketserver模块中的多线程

Python网络编程篇之socketserver

python-socketServer

Python使用socketserver建立一个异步TCP服务器

python-41-初识hmac与socketserver模块

Python——socketserver编程(客户端/服务器)