ThreadingTCPServer 如何设置端口重用

一个典型的TCPServer的建立

    #ThreadingTCPServer从ThreadingMixIn和TCPServer继承  
    #class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass  
    server = ThreadingTCPServer(addr, MyStreamRequestHandlerr)  
    server.serve_forever()
  •     #ThreadingTCPServer从ThreadingMixIn和TCPServer继承  
        #class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass  
        server = ThreadingTCPServer(addr, MyStreamRequestHandlerr)  
        server.serve_forever()

查看SocketServer.py的实现

    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        """Constructor.  May be extended, do not override."""
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            self.server_bind()
            self.server_activate()

    def server_bind(self):
        """Called by constructor to bind the socket.

        May be overridden.

        """
        if self.allow_reuse_address:
            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()
  •    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
            """Constructor.  May be extended, do not override."""
            BaseServer.__init__(self, server_address, RequestHandlerClass)
            self.socket = socket.socket(self.address_family,
                                        self.socket_type)
            if bind_and_activate:
                self.server_bind()
                self.server_activate()
    
        def server_bind(self):
            """Called by constructor to bind the socket.
    
            May be overridden.
    
            """
            if self.allow_reuse_address:
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind(self.server_address)
            self.server_address = self.socket.getsockname()

可以看到,在init初始化里面就已经进行了bind操作,之后再单独设置server的socket选项将不起作用,这就是为什么很多人遇到了直接使用对象的setsockopt方法感觉没有生效,端口有TIME_WAIT的状态,再次运行程序仍然会报Address Already In Use 的错误。

server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
  • server.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

解决方案:

方案一

继承SocketServer.ThreadingTCPServer,在init之前设置allow_reuse_address = True(默认为False)

class EchoServer(SocketServer.ThreadingTCPServer):
    allow_reuse_address = True
    daemon_threads = True
    def __init__(self, server_address, RequestHandlerClass):
        """Set up an initially empty mapping between a user' s nickname
        and the file-like object used to send data to that user."""
        SocketServer.ThreadingTCPServer.__init__(self, server_address, RequestHandlerClass)
  • class EchoServer(SocketServer.ThreadingTCPServer):
        allow_reuse_address = True
        daemon_threads = True
        def __init__(self, server_address, RequestHandlerClass):
            """Set up an initially empty mapping between a user' s nickname
            and the file-like object used to send data to that user."""
            SocketServer.ThreadingTCPServer.__init__(self, server_address, RequestHandlerClass)

方案二

重载Server_bind,在bind之前设置socket选项

    def server_bind(self):
        """Called by constructor to bind the socket.

        May be overridden.

        """
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.socket.bind(self.server_address)
        self.server_address = self.socket.getsockname()




原文地址:https://blog.csdn.net/northwood/article/details/46455825


原文地址:https://www.cnblogs.com/alex-hrg/p/8992389.html