我正在使用模块编写一个简单的套接字服务器socketserver,除了一件小事情之外,一切似乎都工作得很好。我将服务器绑定到某个端口,然后设置server.allow_reuse_address = True为重用同一端口,而不必等待内核释放底层端口。但是,如果在创建服务器实例后修改变量,则它不起作用server.allow_reuse_address = True,但如果我为服务器创建自定义类,然后覆盖其中的变量,则一切正常。
下面是我的代码。
import socketserver
import sys
class MyTCPRequestehandler(socketserver.BaseRequestHandler):
def handle(self):
self.data = self.request.recv(1024)
while self.data:
print('Received {} from {}'.format(self.data.decode().strip(), self.client_address))
self.request.send(self.data.upper())
self.data = self.request.recv(1024)
if __name__ == '__main__':
try:
server = socketserver.TCPServer(('', 12345), MyTCPRequestehandler)
ip, port = server.server_address
server.allow_reuse_address = True
print(server.allow_reuse_address)
print('Server listening on port {}'.format(port))
# server.handle_request()
server.serve_forever()
except KeyboardInterrupt:
sys.exit()
Run Code Online (Sandbox Code Playgroud)
如果在断开连接后重新运行应用程序,我会收到此错误
File "/Documents/PythonPrograms/network-modules/socketServer/simplesocketserver.py", line 16, in <module>
server = socketserver.TCPServer(('', 12345), MyTCPRequestehandler)
File "/spare/ssd/rbhanot/anaconda3/lib/python3.6/socketserver.py", line 453, in __init__
self.server_bind()
File "/spare/ssd/rbhanot/anaconda3/lib/python3.6/socketserver.py", line 467, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
Run Code Online (Sandbox Code Playgroud)
但是,如果我做下面这样的事情,一切都会正常。
class MyTcpServer(socketserver.TCPServer):
allow_reuse_address = True
def __init__(self, address, request_handler_class):
self.address = address
self.request_handler_class = request_handler_class
super().__init__(self.address, self.request_handler_class)
Run Code Online (Sandbox Code Playgroud)
那么我在这里缺少什么?
这是预期且有记录的行为。来自https://svn.python.org/projects/python/trunk/Lib/SocketServer.py:
可以被派生类或实例覆盖的类变量:
- 暂停
- 地址族
- 套接字类型
- 允许重用地址
如果我们进一步检查源代码,我们可以看到其中的原因。类 init 调用server_bind(),该函数检查allow_reuse_address变量并setsockopt根据需要执行相应操作。
如果您稍后更改它,则在实例初始化后不会进行进一步的检查,这意味着您的更改不会影响任何内容。