You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 16:54:03