zoukankan      html  css  js  c++  java
  • Linux端口被占用的解决(附Python专版)

    先说一般情况的解决:

    lsof -i:8000 查出PID,然后 kill掉程序,接着就可以了


    软件重启之后绑定没有释放,lsof -i:8080也查不出来占用的情况

    再来个长连接版Python解决法:(软件重启之后绑定没有释放,lsof -i:8080也查不出来占用的情况)

    OSError: [Errno 98] Address already in use

    端口被占的处理: tcp_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)

    一般情况图示:

    解决后图示:

    完整示例代码:

    from socket import socket, SOL_SOCKET, SO_REUSEADDR
    
    def main():
        with socket() as tcp_socket:
            # 防止端口占用
            tcp_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
            # 绑定端口
            tcp_socket.bind(('', 8080))
            # 监听
            tcp_socket.listen()
            # 等待
            client_socket, address = tcp_socket.accept()
            # 收发消息
            with client_socket:
                print(f"[来自{address}的消息:
    ")
                msg = client_socket.recv(2048)
                if msg:
                    print(msg.decode("utf-8"))
                client_socket.send(
                    """HTTP/1.1 200 ok
    Content-Type: text/html;charset=utf-8
    
    <h1>哈哈哈</h1>"""
                    .encode("utf-8"))
    
    if __name__ == "__main__":
        main()
    

    服务器版解决

    from socket import SOL_SOCKET, SO_REUSEADDR
    from socketserver import ThreadingTCPServer, BaseRequestHandler
    
    class MyHandler(BaseRequestHandler):
        def handle(self):
            print(f"[来自{self.client_address}的消息:]")
            data = self.request.recv(2048)
            print(data)
            self.request.send(
                "HTTP/1.1 200 ok
    Content-Type: text/html;charset=utf-8
    
    <h1>小明,晚上吃鱼汤吗?</h1>"
                .encode("utf-8"))
    
    def main():
        # bind_and_activate=False 手动绑定和激活
        with ThreadingTCPServer(('', 8080), MyHandler, False) as server:
            # 防止端口占用
            server.socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
            server.server_bind()  # 自己绑定
            server.server_activate()  # 自己激活
            server.serve_forever()
    
    if __name__ == "__main__":
        main()
    

    解决前:

    解决后:

    这个就涉及到`TCP4次握手`相关的内容了,如果不是长连接,你先断开客户端,再断开服务端就不会遇到这个问题了,具体问题下次继续探讨~

    有时候会这样简化写(虽然简化了,但有时候也会出现端口占用的情况)

    from socket import SOL_SOCKET, SO_REUSEADDR
    from socketserver import ThreadingTCPServer, BaseRequestHandler
    
    class MyHandler(BaseRequestHandler):
        def handle(self):
            print(f"[来自{self.client_address}的消息:]")
            data = self.request.recv(2048)
            print(data)
            self.request.send(
                "HTTP/1.1 200 ok
    Content-Type: text/html;charset=utf-8
    
    <h1>小明,晚上吃鱼汤吗?</h1>"
                .encode("utf-8"))
    
    def main():
        # 防止端口占用
        ThreadingTCPServer.allow_reuse_address = True
        with ThreadingTCPServer(('', 8080), MyHandler) as server:
            server.serve_forever()
    
    if __name__ == "__main__":
        main()
    

    源码比较简单,一看就懂:

    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
        BaseServer.__init__(self, server_address, RequestHandlerClass)
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            try:
                # 看这
                self.server_bind()
                self.server_activate()
            except:
                self.server_close()
                raise
    
    def server_bind(self):
        # 看这
        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()
    
  • 相关阅读:
    Flex上传文件报“Error #2038”
    AMQ9558
    perl 运算符
    linux gdm 远程桌面访问
    perl 捕获变量
    android apk嵌套 从一个apk启动另外一个apk
    apk调用另一个apk
    ORA-01591 锁被未决分布式事务处理
    jQuery事件控制点击内容下拉
    作业还是作孽?——Leo鉴书79
  • 原文地址:https://www.cnblogs.com/dotnetcrazy/p/10003762.html
Copyright © 2011-2022 走看看