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
相关产品推荐
相关产品推荐

