先说一般情况的解决:

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



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

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

OSError: [Errno 98] Address already in use
<https://www.cnblogs.com/dotnetcrazy/p/9192089.html#_map9>

端口被占的处理: 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()
 

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信