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

Python Socket发送JSON数据异常:无法流式传输至服务器及客户端

问题排查:流式JSON文本传输失败

我希望将输入文本的每个单词以JSON格式流式发送至服务器,再由服务器转发给所有已连接客户端,但目前数据既未传输到服务器,也未转发给其他客户端。以下是相关代码及运行输出:

客户端代码

import socket
import json
import threading

# 定义服务器IP和端口
SERVER_IP = '44.216.25.181'
SERVER_PORT = 55555

# 创建客户端socket
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((SERVER_IP, SERVER_PORT))

# 接收服务器消息的函数
def receive_messages():
    while True:
        try:
            message = client_socket.recv(1024)
            if not message:
                break

            decoded_message = json.loads(message.decode())
            message_type = decoded_message.get('type')
            data = decoded_message.get('data')
        
            if message_type == 'stream_text':
                # 处理流式文本
                print(f"Received streamed text: {data.get('chunk')}")

        except Exception as e:
            print(f"接收消息出错: {e}")
            break

# 启动接收消息的线程
receive_thread = threading.Thread(target=receive_messages)
receive_thread.start()

# 向服务器发送JSON消息的方法
def send_message(msg_type, data):
    try:
        message = {'type': msg_type, 'data': data}
        json_data = json.dumps(message)
        print(json_data)
        client_socket.send(json_data.encode())

    except Exception as e:
        print(f"发送消息出错: {e}")
        print("与服务器的连接已关闭。")
        client_socket.close()
        
def printEvenLengthWords(s):
    # 分割字符串中的单词
    words = s.split()
    for word in words:
        print(word)
        # 修改:将单词包装在字典中,符合服务端预期格式
        send_message('stream_text', {'word': word})

# 输入字符串
user_input = input("Enter the text : ")

# 调用函数
printEvenLengthWords(user_input)

服务端代码

import socket
import threading
import json

# 定义服务器IP和端口
SERVER_IP = '0.0.0.0'
SERVER_PORT = 55555

# 创建服务器socket
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((SERVER_IP, SERVER_PORT))
server_socket.listen()

# 存储已连接客户端的列表
clients = []

# 向所有客户端广播消息的函数
def broadcast(message):
    # 修改:遍历副本,避免遍历过程中列表变化导致异常
    for client in clients.copy():
        try:
            client.send(message)
        except Exception as e:
            print(f"广播消息出错: {e}")
            clients.remove(client)
            client.close()

# 处理客户端连接的函数
def handle_client(client_socket):
    while True:
        try:
            # 接收客户端数据
            message = client_socket.recv(1024)
            if not message:
                break

            # 解码JSON消息
            decoded_message = json.loads(message.decode())

            # 区分消息类型
            message_type = decoded_message.get('type')
            data = decoded_message.get('data')

            if message_type == 'stream_text':
                # 修改:获取正确的字段,客户端传的是'word'
                generated_text = data.get('word')
                print(f"Received streamed text: {generated_text}")

                # 将单词按块广播给所有客户端
                chunk_size = 5
                chunks = [generated_text[i:i + chunk_size] for i in range(0, len(generated_text), chunk_size)]

                for chunk in chunks:
                    chunk_message = json.dumps({'type': 'stream_text', 'data': {'chunk': chunk}})
                    # 修改:广播前编码为字节流
                    broadcast(chunk_message.encode())
        except Exception as e:
            print(f"处理客户端连接出错: {e}")
            # 移除客户端并关闭连接
            if client_socket in clients:
                clients.remove(client_socket)
            client_socket.close()
            break

# 接受 incoming 连接,为每个客户端启动新线程
while True:
    client_socket, client_address = server_socket.accept()
    clients.append(client_socket)
    print(f"新客户端连接: {client_address}")
    client_thread = threading.Thread(target=handle_client, args=(client_socket,))
    client_thread.start()

原运行输出

$ python3 client1.py 
Enter the text : this is a test
this
{"type": "stream_text", "data": "this"}
is
{"type": "stream_text", "data": "is"}
a
{"type": "stream_text", "data": "a"}
test
{"type": "stream_text", "data": "test"}

问题排查与修复点

  • 数据格式不匹配:客户端发送的data是字符串(如"this"),但服务端尝试用data.get('data')读取字典字段,导致解析失败触发异常,直接断开连接。修复:客户端发送时将单词包装为字典{'word': word},服务端对应读取data.get('word')。
  • 广播未编码:服务端广播时直接发送JSON字符串,未编码为字节流,触发发送错误。修复:广播前调用.encode()将字符串转为字节。
  • 语法错误:服务端打印语句print(f"Received streamed text: {generated_text})")多了一个右括号,导致语法错误。修复:修正括号位置。
  • 异常处理不明确:原代码异常捕获太笼统,未打印具体错误信息,难以定位问题。修复:添加具体异常打印。
  • 遍历客户端列表风险:原广播函数直接遍历clients列表,若遍历中客户端断开导致列表变化,会引发异常。修复:遍历列表副本clients.copy()。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 06:17:43