TCP客户端连接报Errno98地址已占用,端口清理后仍未解决
解决TCP客户端连接时的
OSError: [Errno 98] Address already in use问题 问题描述
我用单线程TCP客户端/服务器程序实现文件传输,客户端发起连接时触发OSError: [Errno 98] Address already in use错误。已提前清理端口6006,且确认端口在有效范围内。执行命令如下:
- 服务器端:
./info.py -r -p 6006 - - 客户端:
./info.py -t -p 6006 -ip 127.0.0.1 -
相关代码:
服务器端函数
def ifTcpserver(): serverIP = "127.0.0.1" serverPort = 6006 serverSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serverAddr = (serverIP,serverPort) serverSock.bind(serverAddr) serverSock.listen(1) print(f"listening on port {serverPort}") while True: connectSock, addr = serverSock.accept() jsonBytes = connectSock.recv(1024) print("data:",jsonBytes.decode("UTF-8")) ifDic = json.loads(jsonBytes) print(ifDic, type(ifDic)) connectSock.close()
客户端函数
def ifTcpclient(localInfo): serverIP = "127.0.0.1" serverPort = 6006 jsonMessage = localInfo clientSocket = socket.socket (socket.AF_INET, socket.SOCK_STREAM) sockAddr = (serverIP, serverPort) clientSocket.connect(sockAddr) jsonBytes = jsonMessage.encode("UTF-8") clientSocket.send(jsonBytes) clientSocket.close()
原因分析
- TCP端口TIME_WAIT状态:服务器进程退出后,操作系统会保留端口一段时间(通常1-2分钟,即2倍MSL时长),防止残留数据包干扰新连接,此时端口处于TIME_WAIT状态,无法立即复用。
- 服务器套接字未正确释放:当前服务器代码未处理进程中断场景(如Ctrl+C),监听套接字
serverSock可能未被正确关闭,导致端口被异常占用。 - 重复启动服务器进程:可能存在未完全终止的服务器进程,持续占用端口6006。
解决方案
1. 启用端口复用选项
在服务器绑定端口前,添加SO_REUSEADDR套接字选项,允许复用处于TIME_WAIT状态的端口。同时添加中断捕获逻辑,确保监听套接字正常关闭:
def ifTcpserver(): serverIP = "127.0.0.1" serverPort = 6006 serverSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 允许复用TIME_WAIT状态的端口 serverSock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) serverAddr = (serverIP,serverPort) serverSock.bind(serverAddr) serverSock.listen(1) print(f"listening on port {serverPort}") try: while True: connectSock, addr = serverSock.accept() jsonBytes = connectSock.recv(1024) print("data:",jsonBytes.decode("UTF-8")) ifDic = json.loads(jsonBytes) print(ifDic, type(ifDic)) connectSock.close() except KeyboardInterrupt: # 捕获Ctrl+C信号,关闭监听套接字 serverSock.close() print("Server stopped.")
2. 强制终止占用端口的进程
用以下命令定位并终止占用6006端口的进程:
# 查找进程PID lsof -i :6006 # 或 netstat -tulpn | grep 6006 # 强制终止进程 kill -9 <进程PID>
3. 同步代码与命令行参数
当前代码硬编码了端口6006,建议读取命令行传入的-p参数,避免代码与实际运行参数不一致:
# 服务器端示例:读取命令行端口参数 import argparse parser = argparse.ArgumentParser() parser.add_argument('-p', '--port', type=int, required=True) args = parser.parse_args() serverPort = args.port
客户端同理读取-p参数,确保两端端口一致。
4. 客户端添加异常处理
为客户端连接逻辑添加异常捕获,避免直接崩溃:
def ifTcpclient(localInfo): serverIP = "127.0.0.1" serverPort = 6006 jsonMessage = localInfo clientSocket = socket.socket (socket.AF_INET, socket.SOCK_STREAM) try: sockAddr = (serverIP, serverPort) clientSocket.connect(sockAddr) jsonBytes = jsonMessage.encode("UTF-8") clientSocket.send(jsonBytes) except OSError as e: print(f"Connection failed: {e}") finally: clientSocket.close()
内容的提问来源于stack exchange,提问作者Big_Mann_98
相关产品推荐
相关产品推荐

