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

Python Socket开发报错ValueError: invalid literal for int() with base 10: ''求解

问题根因
  • 核心问题:TCP是字节流协议,没有内置消息边界,你当前直接用recv(2048)无法保证每次读取到完整的单条坐标消息,可能出现半条消息、多条消息拼接的情况,导致split(',')后得到空字符串,转int时报错。
  • 次要问题:你给玩家坐标加的是0.3的浮点增量,直接转字符串后会带小数点,read_pos直接转int也会触发格式错误。
解决方案实现

你设想的「报文头部加预期长度」的方案是正确的,我们采用固定2字节的大端格式长度头(最大支持65535字节的消息,完全满足需求),收发逻辑统一为:

  • 发送时:先打包消息长度为2字节的头部,再发送头部+实际消息内容
  • 接收时:先读取2字节头部得到消息长度,再循环读取直到拿到完整长度的消息内容

完整修改后的代码

Server.py

import threading
import sys
import socket
import struct  # 新增:用于打包解包长度头

server = "127.0.0.1"
port = 2300

pos = [(0, 0), (200, 200)]
playerr = 0

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

try:
    s.bind((server, port))
except socket.error as e:
    print(e)
    sys.exit()

s.listen(2)
print("Waiting for a connection, Server Started")
sys.stdout.flush()

# 新增:统一发送消息函数
def send_msg(conn, data):
    # 打包消息长度为2字节大端整数
    header = struct.pack('!H', len(data))
    conn.sendall(header)
    conn.sendall(data.encode())

# 新增:统一接收消息函数
def recv_msg(conn):
    # 先收2字节头部
    header = conn.recv(2)
    if not header:
        return None
    msg_len = struct.unpack('!H', header)[0]
    # 循环收满指定长度的消息
    msg = b''
    while len(msg) < msg_len:
        chunk = conn.recv(msg_len - len(msg))
        if not chunk:
            return None
        msg += chunk
    return msg.decode()

def read_pos(str):
    str = str.split(",")
    return int(float(str[0])), int(float(str[1]))  # 修改:兼容浮点格式的坐标


def make_pos(tup):
    return str(tup[0]) + "," + str(tup[1])

def threaded_client(conn, player):
    # 修改:用send_msg发送初始位置
    send_msg(conn, make_pos(pos[player]))
    while True:
        try:
            # 修改:用recv_msg接收数据
            data_str = recv_msg(conn)
            if not data_str:
                print("Disconnected")
                break
            data = read_pos(data_str)
            pos[player] = data
            if player == 0:
                reply = pos[1]
            else:
                reply = pos[0]
            print("Received: ", data)
            print("Sending : ", reply)
            # 修改:用send_msg发送回复
            send_msg(conn, make_pos(reply))
        except Exception as e:
            print(e)
            break

    print("Lost connection")
    conn.close()

while True:
    conn, addr = s.accept()
    print("Connected to:", addr)

    t = threading.Thread(target=threaded_client, args=(conn, playerr))
    t.start()
    playerr += 1

test.py(客户端)

import pygame as pg
import socket
import struct  # 新增:用于打包解包长度头

# 新增:统一发送消息函数
def send_msg(conn, data):
    header = struct.pack('!H', len(data))
    conn.sendall(header)
    conn.sendall(data.encode())

# 新增:统一接收消息函数
def recv_msg(conn):
    header = conn.recv(2)
    if not header:
        return None
    msg_len = struct.unpack('!H', header)[0]
    msg = b''
    while len(msg) < msg_len:
        chunk = conn.recv(msg_len - len(msg))
        if not chunk:
            return None
        msg += chunk
    return msg.decode()

def connect():
    try:
        client.connect(addr)
        # 修改:用recv_msg接收初始位置
        return recv_msg(client)
    except Exception as e:
        print(e)
        pg.quit()
        exit()

def send_package(data):
    try:
        send_msg(client, data)
        # 修改:用recv_msg接收回复
        return recv_msg(client)
    except socket.error as e:
        print(e)
        pg.quit()
        exit()

def get_pos():
    keys = pg.key.get_pressed()
    if keys[pg.K_LEFT]:
        sprite1.vx = -0.3
    if keys[pg.K_RIGHT]:
        sprite1.vx = 0.3
    if keys[pg.K_UP]:
        sprite1.vy = -0.3
    if keys[pg.K_DOWN]:
        sprite1.vy = 0.3

def update_pos():
    sprite1.x += sprite1.vx
    sprite1.y += sprite1.vy
    sprite1.vx, sprite1.vy = 0, 0
    sprite1.rect = pg.Rect(sprite1.x, sprite1.y, 75, 75)

def update_other():
    sprite2.rect = pg.Rect(sprite2.x, sprite2.y, 75, 75)

def stop_unboud():
    if sprite1.x < 0:
        sprite1.x = 0
    if sprite1.y < 0:
        sprite1.y = 0
    if sprite1.x > 724:
        sprite1.x = 724
    if sprite1.y > 524:
        sprite1.y = 524

def read_pos(str):
    str = str.split(",")
    return int(float(str[0])), int(float(str[1]))  # 修改:兼容浮点格式坐标

def make_pos(tup):
    return str(tup[0]) + "," + str(tup[1])


client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server = "127.0.0.1"
port = 2300
addr = (server, port)
pos = read_pos(connect())

pg.init()
window = pg.display.set_mode((800, 600))
sprite1 = pg.sprite.Sprite()
sprite1.image = pg.Surface((75, 75))
sprite1.image.fill((255, 0, 0))
sprite1.x = pos[0]
sprite1.y = pos[1]
sprite1.vx, sprite1.vy = 0,0
sprite1.rect = pg.Rect(sprite1.x, sprite1.y, 75, 75)

sprite2 = pg.sprite.Sprite()
sprite2.image = pg.Surface((75, 75))
sprite2.image.fill((0, 0, 255))  # 改蓝色区分两个玩家
sprite2.x = 200
sprite2.y = 200
sprite2.vx, sprite2.vy = 0,0
sprite2.rect = pg.Rect(sprite2.x, sprite2.y, 75, 75)


all_group = pg.sprite.Group([sprite1, sprite2])

run = True
while run:
    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False

    p2Pos = read_pos(send_package(make_pos((sprite1.x, sprite1.y))))
    sprite2.x = p2Pos[0]
    sprite2.y = p2Pos[1]
    update_other()

    get_pos()
    stop_unboud()
    update_pos()


    window.fill(0)
    all_group.draw(window)
    pg.display.flip()

pg.quit()
exit()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 14:54:07