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

Wasm客户端发送Game类型消息时出现Unexpected end of file错误原因排查

Wasm平台发送Game类型消息时出现"Unexpected end of file"错误的排查

项目背景

我正在开发Freeciv游戏的在线版本,基于Bevy引擎,支持原生和Wasm双平台。此前长时间仅验证Wasm版本编译通过,未实际运行测试,近期发现网络层出现异常错误。由于无法编写最小复现代码,且对Wasm不熟悉(依赖Bevy完成大部分相关工作),多日尝试后暂时搁置问题。

核心架构与代码片段

服务器端(基于message-io库)

服务器同时监听TCP和WebSocket端口,收到消息后通过bincode反序列化为指定消息类型:

let (handler, node_listener) = node::split::<Signal>();

info!(
    "Starting TCP {} and Ws {}",
    &self.tcp_listen_addr, &self.ws_listen_addr
);
handler
    .network()
    .listen(Transport::FramedTcp, &self.tcp_listen_addr)
    .unwrap();
handler
    .network()
    .listen(Transport::Ws, &self.ws_listen_addr)
    .unwrap();

// [...]

node_listener.for_each(move |event| match event {
    node::NodeEvent::Network(event) => match event {
        NetEvent::Connected(_, _) => unreachable!(), // 未调用connect()
        NetEvent::Accepted(_, _) => {}
        NetEvent::Message(endpoint, input_data) => {
            let message = match bincode::deserialize::<ClientToServerMessage>(input_data) {
                Ok(message) => message,
                Err(error) => {
                    log::error!("Receive error: {error}");
                    return;
                }
            };
         // 处理消息逻辑 [...]

原生客户端发送逻辑

使用message-io的handler发送序列化后的消息:

// message 为 ClientToServerMessage 类型
let message = bincode::serialize(&message).unwrap();
handler.network().send(server, &message);

Wasm客户端发送逻辑

使用async-wsocket库发送二进制消息:

// message 为 ClientToServerMessage 类型
let bytes = bincode::serialize(&message).unwrap();
tx.send(WsMessage::Binary(bytes)).await.unwrap();

消息结构定义(部分)

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ClientToServerMessage {
    Network(ClientToServerNetworkMessage),
    Game(ClientToServerGameMessage),
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ClientToServerNetworkMessage {
    Hello(Client, Resolution),
    Goodbye,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ClientToServerGameMessage {
    Establishment(ClientToServerEstablishmentMessage),
    InGame(ClientToServerInGameMessage),
}

// [...]

已知事实

  • 原生版本运行完全正常
  • Wasm版本发送ClientToServerMessage::Network类型消息时,服务器能正常反序列化;但发送ClientToServerMessage::Game类型消息时,服务器执行bincode::deserialize会抛出io error: unexpected end of file错误
  • Wasm版本数月前运行正常,之后进行了未涉及网络层的代码重构,但因未定期测试Wasm版本,无法通过Git bisect定位问题

本地复现步骤(Ubuntu验证通过,Windows/Mac理论适用)

  1. 克隆项目并启动服务器:
git clone git@github.com:buxx/civ.git
git checkout fix-wasm-message
cargo run --bin world --release -- ./world 5000 5000
cargo run --release --bin server -- ./world
  1. 构建并启动Wasm HTTP服务器:
./build_wasm.sh && http-server wasm
  1. 打开页面操作:访问http://127.0.0.1:7878/index.html,点击两次"Connect"(此时Network消息已成功发送并处理),选择国家后点击"Join",服务器端会出现目标错误。

问题

Wasm平台下发送ClientToServerMessage::Game类型消息时,出现"Unexpected end of file"错误的原因是什么?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 05:40:07