• 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


  • 相关阅读:
    libcurl的内存泄露的坑
    Linux 经典面试题(转)
    全栈项目|小书架|服务器开发-Koa2 全局异常处理
    强大的CompletableFuture
    如何进行kubernetes问题的排障
    Golang的json包
    JAVA面试题:Spring中bean的生命周期(转)
    建造者模式
    Netty学习篇④-心跳机制及断线重连
    Fabric1.4:手动启动 first-network 网络(三)
  • 原文地址:https://www.cnblogs.com/alex-hrg/p/8992389.html
Copyright © 2020-2023  润新知