Ubuntu下Python TCP服务端设SO_REUSEADDR仍报端口占用问题求助
问题根因与修复方案
核心问题1:代码缩进错误导致逻辑异常
你提供的代码缩进层级完全混乱,try 块、数据处理逻辑、except 块的归属关系错误,会触发未定义变量、异常无法捕获的问题,最终导致服务端进程意外崩溃。进程崩溃时服务端套接字未正常关闭,端口被处于 TIME_WAIT 状态的连接占用,重启服务端时就会触发port already in use报错。
核心问题2:未处理客户端正常断开的场景
当客户端主动关闭连接时,sock.recv()会返回空字节,现有代码没有对该场景做判断,不会主动释放客户端套接字资源,长期运行会导致资源泄漏,也会引发端口占用问题。
修复建议
1. 修正代码缩进与逻辑
修正后的完整可运行代码如下:
#!/usr/bin/python3 import socket import select def main(): CONNECTION_LIST = [] # socket客户端列表 RECV_BUFFER = 4096 PORT = 50001 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 同时设置REUSEADDR和REUSEPORT,确保端口可快速复用 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEPORT, 1) server_socket.bind(('0.0.0.0', PORT)) server_socket.listen(10) # 将服务端socket加入可读连接列表 CONNECTION_LIST.append(server_socket) print("服务端已启动,端口:" + str(PORT)) while 1: # 通过select获取就绪的可读socket read_sockets, write_sockets, error_sockets = select.select(CONNECTION_LIST, [], []) for sock in read_sockets: # 新连接请求 if sock == server_socket: sockfd, addr = server_socket.accept() CONNECTION_LIST.append(sockfd) print("客户端(%s, %s)已连接" % addr) # 客户端发送的消息 else: try: data = sock.recv(RECV_BUFFER) # 客户端主动断开连接,recv返回空字节 if not data: print("客户端(%s, %s)主动断开连接" % addr) sock.close() CONNECTION_LIST.remove(sock) continue print(data) # 注意:recv返回的是字节类型,需要解码后再判断前缀 if data.decode().startswith("CLIENT1_"): sock.sendall(b"client1") elif data.decode().startswith("CLIENT2_"): sock.sendall(b"client2") # 连接异常处理 except Exception as e: print("客户端(%s, %s)连接异常,已离线" % addr) sock.close() CONNECTION_LIST.remove(sock) continue server_socket.close() if __name__ == "__main__": main()
2. 补充优化说明
- 新增
SO_REUSEPORT参数设置,适配Linux内核下的端口快速复用场景 - 增加空数据判断逻辑,主动处理客户端正常断开的场景
- 修复字节/字符串类型判断问题,原代码直接对字节类型调用
startswith传入字符串会触发报错 - 修正
sendall的入参类型,需要传入字节而非字符串 - 调整异常捕获逻辑,避免全局捕获所有异常导致问题无法排查
内容的提问来源于stack exchange,提问作者Jaume
相关产品推荐
相关产品推荐

