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建立一个异步TCP服务器