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

解决TypeError: list indices must be integers, not sockets报错

错误根因

报错触发原因是混淆了Python列表与字典的索引规则:

  • 列表(list)仅支持整数、切片作为合法索引,不支持传入socket套接字对象作为下标取值
  • 你的代码中clients被定义为列表,存储的是accept()返回的客户端socket对象,但执行clients[client].send()时直接把socket对象本身作为索引传入,不符合列表索引要求,因此抛出TypeError: list indices must be integers or slices, not sockets。

如果你坚持用列表存储客户端,需要先通过clients.index(client)获取socket对应的整数下标再取值,但这种方式需要遍历全量列表、匹配效率低,出现重复socket对象时会匹配错误,完全不适配备注客户端身份、发送定向消息的场景,不推荐使用。

可运行正确实现方案

核心调整是将客户端存储结构从列表改为字典,以客户端唯一身份标识作为key,对应的socket连接对象作为value,同时增加连接握手环节确保身份匹配准确,从根源上避免索引错误。

服务端完整代码

import socket
import threading

# 基础配置
HOST = '0.0.0.0'
PORT = 8888
FORMAT = 'utf-8'
# 用字典存储在线客户端:key=客户端身份,value=对应socket连接对象
online_clients = {}
# 预定义各客户端的专属消息
CLIENT_EXCLUSIVE_MSG = {
    "Iconet": "连接成功,这是下发给Iconet客户端的专属配置消息",
    "Robot": "连接成功,这是下发给Robot客户端的专属控制指令"
}

def handle_client(client_socket, client_addr):
    client_id = None
    try:
        # 握手阶段:客户端连接后第一时间上报自身身份
        client_id = client_socket.recv(1024).decode(FORMAT).strip()
        # 身份校验
        if client_id not in CLIENT_EXCLUSIVE_MSG:
            client_socket.send("非法客户端身份,连接将断开".encode(FORMAT))
            client_socket.close()
            return
        
        # 存入在线客户端字典
        online_clients[client_id] = client_socket
        print(f"客户端[{client_id}]从{client_addr}接入,当前在线:{list(online_clients.keys())}")

        # 发送定向专属消息
        target_msg = CLIENT_EXCLUSIVE_MSG[client_id]
        client_socket.send(target_msg.encode(FORMAT))
        print(f"已向[{client_id}]发送专属消息:{target_msg}")

        # 持续处理客户端上报消息
        while True:
            recv_data = client_socket.recv(1024).decode(FORMAT)
            if not recv_data:
                break
            print(f"收到[{client_id}]消息:{recv_data}")

    except Exception as e:
        print(f"客户端[{client_id}]连接异常:{str(e)}")
    finally:
        # 连接断开时清理残留记录
        if client_id and client_id in online_clients:
            del online_clients[client_id]
        client_socket.close()
        print(f"客户端[{client_id}]已断开,当前在线:{list(online_clients.keys())}")

def start_server():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    server_socket.bind((HOST, PORT))
    server_socket.listen(5)
    print(f"TCP服务端启动完成,监听地址{HOST}:{PORT}")
    while True:
        client_sock, client_addr = server_socket.accept()
        # 每个客户端连接启动独立线程处理
        threading.Thread(target=handle_client, args=(client_sock, client_addr), daemon=True).start()

if __name__ == "__main__":
    start_server()

客户端测试代码

启动两个客户端实例,分别传入对应身份即可测试定向消息效果:

import socket
import sys

HOST = '127.0.0.1'
PORT = 8888
FORMAT = 'utf-8'

def start_client(client_id):
    client_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client_sock.connect((HOST, PORT))
    # 连接建立后第一时间上报身份
    client_sock.send(client_id.encode(FORMAT))
    # 接收服务端专属消息
    welcome_msg = client_sock.recv(1024).decode(FORMAT)
    print(f"[{client_id}] 收到服务端消息:{welcome_msg}")

    # 消息收发测试
    while True:
        input_content = input(f"[{client_id}] 输入发送内容(输入exit退出):")
        if input_content == "exit":
            break
        client_sock.send(input_content.encode(FORMAT))
    client_sock.close()

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("启动方式:python client.py <客户端身份:Iconet/Robot>")
        sys.exit(1)
    start_client(sys.argv[1])
关键修正点
  • 替换客户端存储结构:用字典替代列表,直接通过客户端身份索引对应socket连接,彻底规避列表索引类型错误
  • 增加身份握手逻辑:要求客户端连接后第一时间上报身份,避免按连接顺序匹配客户端导致的消息错发问题
  • 补充异常兜底逻辑:连接断开时自动清理字典内的失效socket记录,避免后续发消息触发无效连接错误
  • 后续如果需要给任意在线客户端发定向消息,直接调用online_clients[目标客户端ID].send(消息内容.encode(FORMAT))即可,无需遍历全量连接,执行效率更高

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 20:21:38