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}的消息:\n") msg = client_socket.recv(2048) if msg: print(msg.decode("utf-8")) client_socket.send( """HTTP/1.1 200 ok\r\nContent-Type: text/html;charset=utf-8\r\n\r\n<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\r\nContent-Type: text/html;charset=utf-8\r\n\r\n<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\r\nContent-Type: text/html;charset=utf-8\r\n\r\n<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()
作者:毒逆天
打赏:18i4JpL6g54yAPAefdtgqwRrZ43YJwAV5z