繁体   English   中英

NetworkStream 读取跳过数据包

[英]NetworkStream read skipping packets

我正在尝试使用 async BeginRead 来实现 TCPClient 以侦听自定义应用程序。 监听代码是这样的:

    ClientState cs;

    void Update()
    {
        lock (lockObj)
        {
            if (cs != null)
            {
                if (cs.bytesReceived > 0)
                {
                    ReceiveNetworkMsg?.Invoke(cs.receiveBuffer, cs.bytesReceived);
                    Array.Clear(cs.receiveBuffer, 0, cs.bytesReceived);
                    cs.bytesReceived = 0;
                }
            }
        }
    }

    IEnumerator ListenForData()
    {
        Debug.Log("Listening");

        stream = client.GetStream();
        cs = new ClientState(stream);

        do
        {
            //stream.BeginRead(buffer, 0, buffer.Length, MessageReceived, client);
            stream.BeginRead(cs.buffer, 0, cs.buffer.Length, new AsyncCallback(ReadCallback), cs);
            yield return null;
        } while (client != null);
    }

    void ReadCallback(IAsyncResult result)
    {
        ClientState cs = (ClientState)result.AsyncState;

        lock (lockObj)
        {
            int currBytesReceived = cs.stream.EndRead(result);
            Array.Copy(cs.buffer, 0, cs.receiveBuffer, cs.bytesReceived, currBytesReceived);
            Debug.Log("Network receiving: " + currBytesReceived + " " + cs.bytesReceived + " bytes. " + BitConverter.ToString(cs.buffer, 0, currBytesReceived));
            cs.bytesReceived += currBytesReceived;
        }
    }

在服务器发送一系列消息的某个时刻,接收到的字节与发送的实际字节不匹配:

Wireshark 日志:

No.     Time           Source                Destination           Protocol Length Info
     35 0.619977       127.0.0.1             127.0.0.1             TCP      64     5001 → 49872 [PSH, ACK] Seq=53 Ack=140 Win=28 Len=20

0000  14 00 23 11 4a 3e 01 01 1c 10 02 00 00 00 00 00   ..#.J>..........
0010  02 01 22 00                                       ..".
    Data: 140023114a3e01011c1002000000000002012200
    [Length: 20]

No.     Time           Source                Destination           Protocol Length Info
     39 0.621735       127.0.0.1             127.0.0.1             TCP      65     5001 → 49872 [PSH, ACK] Seq=73 Ack=140 Win=28 Len=21

0000  15 00 99 b2 b6 07 01 01 06 10 02 00 00 00 00 00   ................
0010  00 00 00 00 00                                    .....
    Data: 150099b2b607010106100200000000000000000000
    [Length: 21]

No.     Time           Source                Destination           Protocol Length Info
     43 0.623598       127.0.0.1             127.0.0.1             TCP      65     5001 → 49872 [PSH, ACK] Seq=94 Ack=140 Win=28 Len=21

0000  15 00 99 b2 b6 07 01 01 06 10 02 00 00 00 00 00   ................
0010  00 00 00 00 00                                    .....
    Data: 150099b2b607010106100200000000000000000000
    [Length: 21]

No.     Time           Source                Destination           Protocol Length Info
     47 0.625630       127.0.0.1             127.0.0.1             TCP      65     5001 → 49872 [PSH, ACK] Seq=115 Ack=140 Win=28 Len=21

0000  15 00 99 b2 b6 07 01 01 06 10 02 00 00 00 00 00   ................
0010  00 00 00 00 00                                    .....
    Data: 150099b2b607010106100200000000000000000000
    [Length: 21]

No.     Time           Source                Destination           Protocol Length Info
     51 0.627592       127.0.0.1             127.0.0.1             TCP      65     5001 → 49872 [PSH, ACK] Seq=136 Ack=140 Win=28 Len=21

0000  15 00 99 b2 b6 07 01 01 06 10 02 00 00 00 00 00   ................
0010  00 00 00 00 00                                    .....
    Data: 150099b2b607010106100200000000000000000000
    [Length: 21]

No.     Time           Source                Destination           Protocol Length Info
     55 0.629683       127.0.0.1             127.0.0.1             TCP      65     5001 → 49872 [PSH, ACK] Seq=157 Ack=140 Win=28 Len=21

0000  15 00 99 b2 b6 07 01 01 06 10 02 00 00 00 00 00   ................
0010  00 00 00 00 00                                    .....
    Data: 150099b2b607010106100200000000000000000000
    [Length: 21]

No.     Time           Source                Destination           Protocol Length Info
     59 0.632344       127.0.0.1             127.0.0.1             TCP      65     5001 → 49872 [PSH, ACK] Seq=178 Ack=140 Win=28 Len=21

0000  15 00 99 b2 b6 07 01 01 06 10 02 00 00 00 00 00   ................
0010  00 00 00 00 00                                    .....
    Data: 150099b2b607010106100200000000000000000000
    [Length: 21]

No.     Time           Source                Destination           Protocol Length Info
     65 0.634544       127.0.0.1             127.0.0.1             TCP      62     5001 → 49872 [PSH, ACK] Seq=199 Ack=166 Win=28 Len=18

0000  12 00 57 c1 55 6c 01 01 03 10 02 01 00 00 00 00   ..W.Ul..........
0010  00 02                                             ..
    Data: 120057c1556c010103100201000000000002
    [Length: 18]

日志:

Network receiving: 20 0 bytes. 14-00-9D-59-A2-54-01-01-1C-10-02-00-00-00-00-00-02-01-1F-00

Network receiving: 21 20 bytes. 15-00-99-B2-B6-07-01-01-06-10-02-00-00-00-00-00-00-00-00-00-00

Network receiving: 21 41 bytes. 15-00-99-B2-B6-07-01-01-06-10-02-00-00-00-00-00-00-00-00-00-00

Network receiving: 21 62 bytes. 15-00-99-B2-B6-07-01-01-06-10-02-00-00-00-00-00-00-00-00-00-00

Network receiving: 21 83 bytes. 15-00-99-B2-B6-07-01-01-06-10-02-00-00-00-00-00-00-00-00-00-00

Network receiving: 21 104 bytes. 15-00-99-B2-B6-07-01-01-06-10-02-00-00-00-00-00-00-00-00-00-00

Network receiving: 21 0 bytes. 12-00-57-C1-55-6C-01-01-03-10-02-01-00-00-00-00-00-02-00-00-00

Network receiving: 18 21 bytes. 12-00-57-C1-55-6C-01-01-03-10-02-01-00-00-00-00-00-02

在 20 字节消息之后,在 18 字节消息之前应该有 6 个 21 字节消息。 我的接收端首先处理前 5 个 21 字节的消息,然后由于某种原因,当它试图处理第 6 个 21 字节的消息时,它返回了正确的大小,但它得到的是 18 字节的消息。

我在这里错过了一些基本的东西吗?

网络 stream 收到 21 个字节 6 次; ClientState在 104 和 0 之间对它们做了什么 - 取决于ClientState ,其中:我们看不到。 听起来像是一个竞争线程让ClientState消耗了缓冲区。 但是请注意,IMO 您的期望在这里是不正确的; 我从根本上不同意以下说法:

在 18 字节 1 之前应该有 6 条 21 字节消息

我们正在查看的代码是 TCP,它处理的是流,而不是消息; 不能保证它会以 6 个 21 字节的片段到达。 它可以全部以单个 126 字节块的形式出现,也可以以 126 个单独的 1 字节块的形式出现。 您所保证的是:相同顺序的相同字节(或者如果检测到损坏的套接字,可能会失败)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM