socketserver - 允许重用地址重新绑定现有端口号在不覆盖类变量的情况下不起作用

Roh*_*hit 4 python python-3.x

我正在使用模块编写一个简单的套接字服务器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)

那么我在这里缺少什么?

Han*_*nnu 5

这是预期且有记录的行为。来自https://svn.python.org/projects/python/trunk/Lib/SocketServer.py

可以被派生类或实例覆盖的类变量:

  • 暂停
  • 地址族
  • 套接字类型
  • 允许重用地址

如果我们进一步检查源代码,我们可以看到其中的原因。类 init 调用server_bind(),该函数检查allow_reuse_address变量并setsockopt根据需要执行相应操作。

如果您稍后更改它,则在实例初始化后不会进行进一步的检查,这意味着您的更改不会影响任何内容。