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

异步Server Socket无法处理多条消息问题求助

问题分析与修复方案

看了你的代码,问题主要出在ReadCallback方法的逻辑顺序和后续接收的处理上,咱们一步步拆解:

1. 数据接收与处理的顺序完全搞反了

你现在的代码是先调用BeginReceive,再把刚收到的数据追加到StringBuilder里,这会导致:

  • 第一次接收的39字节消息,其实是在第二次进入ReadCallback时才被处理(因为第一次调用BeginReceive后,后续的接收触发才会处理之前的数据)
  • 后续的消息因为接收和处理的时序混乱,根本没被正确累积和解析

2. 仅在特定条件下才继续监听后续消息

你的代码里只有当fields[1] == "0"时才再次调用BeginReceive,如果后续消息的fields[1]不是0,服务器就停止监听了,自然收不到后续消息。

3. 没有正确判断单条消息的完整性

Socket是基于流的,不是基于消息的,你不能假设一次BeginReceive就能拿到完整的一条消息。虽然你第一条消息刚好39字节被一次接收,但后续消息可能被拆分包,或者多条消息连在一起发送,这时候你的代码会把多条消息混在一起解析,直接导致逻辑错误。


修正后的代码与关键改动

修正ReadCallback方法

private void ReadCallback(IAsyncResult Ar)
{
    // Retrieve the state object and the handler socket
    var state = (StateObject)Ar.AsyncState;
    var handler = state.WorkSocket;

    try
    {
        var bytesRead = handler.EndReceive(Ar);
        if (bytesRead > 0)
        {
            // 第一步:先把收到的数据追加到缓冲区,顺序不能反!
            state.Sb.Append(Encoding.ASCII.GetString(state.Buffer, 0, bytesRead));
            var content = state.Sb.ToString();

            // 第二步:判断当前是否已经收到一条完整的消息
            // 这里假设你的消息是以\r\n作为结束符(从你的TrimEnd('\r', '\n')推测)
            if (content.EndsWith("\r\n"))
            {
                // 处理完整的消息
                Msg.Debug($"Read {content.Length} bytes from socket. \n Data : {content}");
                var fields = content.TrimEnd('\r', '\n').Split(',').ToList();
                
                var paymentDetails = ProcessPaymentResponse(fields);
                if (paymentDetails != null)
                {
                    ResponseQueue.Enqueue(paymentDetails);
                    ResponseResetSignal.Set();
                }

                // 重置StringBuilder,准备接收下一条消息
                state.Sb.Clear();
            }

            // 第三步:不管当前消息是否完整,都要继续监听下一次接收
            // 这是保证能收到后续消息的关键!
            handler.BeginReceive(state.Buffer, 0, StateObject.BUFFER_SIZE, 0, ReadCallback, state);
        }
        else
        {
            // bytesRead为0表示客户端关闭了连接
            Msg.Debug("Client disconnected");
            handler.Shutdown(SocketShutdown.Both);
            handler.Close();
        }
    }
    catch (Exception e)
    {
        Msg.Debug($"Read error: {e.ToString()}");
        handler.Shutdown(SocketShutdown.Both);
        handler.Close();
    }
}

关键改动说明

  • 调整数据处理顺序:先把收到的字节转成字符串追加到StringBuilder,再处理,确保每一次接收的数据都被正确累积。
  • 增加消息完整性判断:通过检查消息是否以\r\n结尾(你原代码里用了TrimEnd,推测这是你的消息结束符),确保只有收到完整的一条消息时才进行业务处理,避免解析不完整的消息。
  • 强制持续监听:不管当前消息是否处理完成,只要客户端还没断开,就再次调用BeginReceive,保证服务器能一直接收后续的消息。
  • 增加异常处理:避免单个连接的异常导致整个服务器崩溃,同时在客户端断开时正确关闭Socket。

额外建议

  • 如果你确定每条消息的长度是固定的(比如都是39字节),也可以通过累积字节数来判断消息完整性,比判断结束符更高效。
  • 异步Socket的状态管理要注意,StateObject里的Buffer和Sb要确保是每个连接独立的,你的代码看起来已经做到了,这点没问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:19:57