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

如何在Python中维护已连接客户端列表以向指定客户端请求文件

Python Socket多线程服务端维护客户端列表的方案

核心思路:用线程安全的存储结构保存所有活跃的客户端连接,接入时注册、断开时注销,需要定向发请求时从存储中取出对应客户端的连接对象即可。

1. 核心改造点

  • 定义全局的客户端存储容器,推荐用字典,方便按唯一标识快速检索,键可以用客户端的(IP,端口)元组,也可以用客户端上报的业务ID,值存储socket连接对象和其他客户端信息
  • 引入线程锁threading.Lock,避免多线程同时读写存储容器时出现竞态问题
  • 在handle_client函数中补充连接断开的清理逻辑,避免无效连接残留

2. 完整修改后的代码

import socket
import threading

# 配置参数请根据自己的需求修改
IP = "0.0.0.0"
PORT = 8888
ADDR = (IP, PORT)

# 全局客户端存储字典:key为(客户端IP, 客户端端口),value为socket连接对象
active_clients = {}
# 操作客户端字典的锁
client_lock = threading.Lock()

def handle_client(conn, addr):
    client_ip, client_port = addr
    print(f"新客户端接入:{client_ip}:{client_port}")
    
    # 接入时将客户端加入存储
    with client_lock:
        active_clients[(client_ip, client_port)] = conn
    
    try:
        # 这里是你原来的客户端处理逻辑,比如接收客户端消息等
        while True:
            data = conn.recv(1024)
            if not data:
                break
            # 处理收到的数据的逻辑写在这里
            print(f"收到{client_ip}:{client_port}的消息:{data.decode()}")
    except Exception as e:
        print(f"客户端{client_ip}:{client_port}连接异常:{str(e)}")
    finally:
        # 断开时从存储中移除客户端
        with client_lock:
            if (client_ip, client_port) in active_clients:
                del active_clients[(client_ip, client_port)]
        conn.close()
        print(f"客户端{client_ip}:{client_port}已断开")

def send_file_request_to_client(target_addr, request_msg):
    """
    向指定客户端发送文件请求的工具函数
    target_addr: 目标客户端的(IP,端口)元组
    request_msg: 给客户端的请求指令,比如"GET_FILE:xxx.txt"
    """
    with client_lock:
        target_conn = active_clients.get(target_addr)
    if not target_conn:
        print(f"目标客户端{target_addr}不在线")
        return False
    try:
        target_conn.send(request_msg.encode())
        return True
    except Exception as e:
        print(f"向{target_addr}发请求失败:{str(e)}")
        # 发送失败说明连接已失效,清理掉
        with client_lock:
            if target_addr in active_clients:
                del active_clients[target_addr]
        target_conn.close()
        return False

def main():
    print("Starting the server")
    server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 使用IPV4和TCP连接
    server.bind(ADDR) # 绑定地址
    server.listen() # 开始监听
    print(f"server is listening on {IP}: {PORT}")
    while True:
        conn, addr = server.accept() # 接受客户端连接
        thread = threading.Thread(target = handle_client, args = (conn, addr)) # 为每个客户端分配线程
        thread.start()
        # 可以在这里测试调用发请求的函数,比如给刚接入的客户端发请求
        # send_file_request_to_client(addr, "GET_FILE:test.txt")

if __name__ == "__main__":
    main()

3. 使用说明

要定向给指定客户端发文件请求时,直接调用send_file_request_to_client函数,传入目标客户端的(IP,端口)和请求指令即可。如果需要更友好的标识,可以在客户端接入后先让客户端上报用户名/设备ID作为字典的key,之后直接用业务ID查找客户端即可,不需要记忆IP端口。

注意事项

  • 所有对active_clients字典的读写操作都必须加锁,避免多线程并发修改导致的数据异常
  • 每次操作连接对象时都要做异常捕获,出现错误及时清理无效连接,避免字典中残留已断开的连接
  • 你可以根据自己的业务需求扩展active_clients存储的内容,比如加入客户端的操作系统、权限等级等额外信息

内容的提问来源于stack exchange,提问作者Trung Nguyen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 21:27:02