Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/323.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 网络流读取跳过数据包_C#_Unity3d - Fatal编程技术网

C# 网络流读取跳过数据包

C# 网络流读取跳过数据包,c#,unity3d,C#,Unity3d,我正在尝试使用async BeginRead来实现TCPClient,以侦听自定义应用程序。监听代码如下: ClientState cs; void Update() { lock (lockObj) { if (cs != null) { if (cs.bytesReceived > 0) {

我正在尝试使用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]
日志:

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


我是不是错过了一些基本的东西?

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

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


我们看到的代码是TCP,它处理的是流,而不是消息;无法保证它将以6个21字节的片段到达。它可以全部到达一个126字节的块,也可以到达126个单独的1字节块。您所能保证的是:相同的字节以相同的顺序排列(或者,如果检测到断开的套接字,可能会出现故障)。

很抱歉,我忘记将使用者放在主线程的更新中(上面也更新了)。@xilef so。。。这看起来就像
Update
发生在最后一条21字节的消息之前,清除了缓冲区;是什么让你觉得这里出了什么问题?请具体说明:什么是你意想不到的?别忘了:你的计数在追加之前;现在还不清楚您是否将字节输出限制在缓冲区的活动部分。是的,在最后的21个字节之前,更新首先处理。在此之后,我希望EndRead将返回最终的21字节大小和缓冲区,以便在wireshark日志中包含上面第59号数据包中的消息。我得到的是一个21字节的大小,但缓冲区包含65号数据包中的消息。@xilef你是从什么得出这个结论的?我熟悉网络代码,我不认为这是一个有效的结论;您应该在这里记录的内容是:
BitConverter.ToString(cs.buffer,0,currBytesReceived)
(在
ReadCallback
期间,理想情况下是在
锁内),因为这就是我们正在接收的内容。从我所看到的情况来看,您看到的其他一切似乎都是关于
Update
的时间问题。它没有显示何时或如何调用
Update
,但这看起来像hellaproblematic@FelixPalomares什么时候进行枚举?我强烈怀疑这里发生的事情是:时机;建议-为“BeginRead”添加日志记录。查看该输出,我认为您的读取频率比您想象的要高(或在不同的时间),并且您的数组被过度标记
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