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

如何使用Python socket实现服务端发多列表、客户端分别接收

实现socket服务端多列表分开收发的方案

核心问题:TCP是面向流的传输协议,没有天然的消息边界,如果直接连续调用send发送3个序列化后的列表,客户端recv时可能一次收到多个序列化数据的拼接内容,也可能分多次收到单个列表的分片数据,无法准确拆分出独立的列表。

下面提供两种可直接运行的实现方案:


方案1:打包一次性传输(改动最小,适合固定发3个列表的场景)

直接把3个列表打包为一个元组序列化后一次性发送,客户端反序列化后直接拆分即可,无需额外处理粘包问题。

改后server.py代码

import socket
import pickle

am0=['AQ-20', 'A3000', 'AQ-26', 'A5000', 'AQ-33', 'A5000pro', 'AQ-33pro']
am1=['A10000Pro', 'AQ-43', 'AX-48', 'AX-58', 'AX-68']
am2=['Material', 'nan', 'Steel', 'Stainless S.', 'Stainless S. 1.403']

# 三个列表打包成元组后序列化
all_data = pickle.dumps((am0, am1, am2))

mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 注意:1024以下是特权端口需要管理员权限,改为12345避免报错
mysocket.bind(('127.0.0.1', 12345))
buffer_size = 1024
mysocket.listen()
(client, (ip,port)) = mysocket.accept()
client.send(all_data)

mysocket.close()

改后client.py代码

import socket
import pickle

host = '127.0.0.1'
port = 12345
buffer_size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

# 一次性接收后反序列化得到三个列表
data = pickle.loads(s.recv(buffer_size))
am0, am1, am2 = data
print(am0)
print(am1)
print(am2)

s.close()

方案2:带长度前缀分开发送(灵活可扩展,适合后续增减发送的列表数量)

每个列表序列化后,先发送4字节的长度标识(用struct模块打包),再发送实际的序列化数据,客户端每次先读取长度,再接收对应长度的字节,即可准确拆分每个独立列表。

改后server.py代码

import socket
import pickle
import struct

am0=['AQ-20', 'A3000', 'AQ-26', 'A5000', 'AQ-33', 'A5000pro', 'AQ-33pro']
am1=['A10000Pro', 'AQ-43', 'AX-48', 'AX-58', 'AX-68']
am2=['Material', 'nan', 'Steel', 'Stainless S.', 'Stainless S. 1.403']

# 序列化每个列表
serial_list = [pickle.dumps(am0), pickle.dumps(am1), pickle.dumps(am2)]

mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysocket.bind(('127.0.0.1', 12345))
buffer_size = 1024
mysocket.listen()
(client, (ip,port)) = mysocket.accept()

# 循环发送每个列表:先发4字节长度,再发实际数据
for item in serial_list:
    # !I 表示网络字节序的无符号整型,占4字节
    client.send(struct.pack('!I', len(item)))
    client.send(item)

mysocket.close()

改后client.py代码

import socket
import pickle
import struct

host = '127.0.0.1'
port = 12345
buffer_size = 1024
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

# 封装读取指定长度字节的函数,避免分片导致数据不全
def recv_exact(n):
    data = b''
    while len(data) < n:
        packet = s.recv(n - len(data))
        if not packet:
            return None
        data += packet
    return data

am_list = []
# 循环接收3次,对应三个列表
for _ in range(3):
    # 先收4字节解出数据长度
    len_bytes = recv_exact(4)
    data_len = struct.unpack('!I', len_bytes)[0]
    # 收对应长度的字节反序列化
    item_data = recv_exact(data_len)
    am_list.append(pickle.loads(item_data))

am0, am1, am2 = am_list
print(am0)
print(am1)
print(am2)

s.close()

注意事项

  • 避免使用1024以下的端口,这类端口属于系统特权端口,需要管理员/root权限才能绑定,建议使用1024~65535之间的未占用端口
  • 如果要发送的列表数据量很大,超过设置的buffer_size,必须用recv_exact这类循环接收的逻辑,保证数据收全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:36:03