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()
    
  • 相关阅读:
    数据库备份脚本
    redismyadmin安装(支持redis4 集群模式)
    elasticsearch ik安装
    centos7.2 +cloudstack 4.11 +KVM +ceph 安装配置(网卡带聚合)
    cloudstack4.11+KVM+4网卡bond5+briage 交换机不作配置
    web service:AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
    根据WSDL生成客户端代码(XFire)
    Apache axis2 + Eclipse 开发 WebService
    The processing instruction target matching "[xX][mM][lL]" is not allowed.
    使用dom4j解析xml文件,并封装为javabean对象
  • 原文地址:https://www.cnblogs.com/dotnetcrazy/p/10003762.html
Copyright © 2011-2022 走看看