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)
一般情况图示:
解决后图示:
完整示例代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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() |
服务器版解决
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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次握手`相关的内容了,如果不是长连接,你先断开客户端,再断开服务端就不会遇到这个问题了,具体问题下次继续探讨~
有时候会这样简化写(虽然简化了,但有时候也会出现端口占用的情况)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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() |
源码比较简单,一看就懂:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?