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