C# TCP客户端/服务器网络流跳过数据包

C# TCP客户端/服务器网络流跳过数据包,c#,.net,winforms,C#,.net,Winforms,在我的程序中的某些时刻,我几乎同时从不同的进程向服务器写入数据。我注意到,当两个数据包几乎立即发送时,其中一个数据包从未到达服务器,尽管使用了TCP,这应该确保数据包被接收 为了测试这一点,我只需一个接一个地发送1000个数据包,没有延迟: NetworkStream stream = server.GetStream(); int i = 0; while (i < 1000) { byte[] data = Encoding.Unicode.GetBytes(i.ToStrin

在我的程序中的某些时刻,我几乎同时从不同的进程向服务器写入数据。我注意到,当两个数据包几乎立即发送时,其中一个数据包从未到达服务器,尽管使用了TCP,这应该确保数据包被接收

为了测试这一点,我只需一个接一个地发送1000个数据包,没有延迟:

NetworkStream stream = server.GetStream();
int i = 0;
while (i < 1000)
{
    byte[] data = Encoding.Unicode.GetBytes(i.ToString() + "$");
    stream.Write(data, 0, data.Length);
    i++;
}
输出:

 >> 0
 >> 1
 >> 20
 >> 76
 >> 108
 >> 136
 >> 163
 >> 197
 >> 220
 >> 241
 >> 276
 >> 302
 >> 330
 >> 372
 >> 373
 >> 469
 >> 507
 >> 530
 >> 560
 >> 590
 >> 628
 >> 651
 >> 683
 >> 722
 >> 747
 >> 772
 >> 803
 >> 826
 >> 861
 >> 889
 >> 913
 >> 950
 >> 980
是什么导致了这种现象

另外,我也尝试过:

var result = stream.WriteAsync(data, 0, data.Length);
result.Wait();
没有运气

更新:

好吧,我很笨。流包含所有其他堆积的文本,我只是用子字符串0,IndexOf将其删除$
所以现在我简单地用新行替换$,但随后我遇到了另一个问题。大约在800-900之间,它再次从500开始计数,然后达到999。这是怎么回事?

我想问题出在这条线路上

        DataFromClient = DataFromClient.Substring(0, DataFromClient.IndexOf("$"));
您假设每次读取将获得1个字符串,但在一次读取中可能有许多可用字符串。你应该试着用split$来代替,并写出所有的结果。您需要随数据一起发送一些有关您正在发送的内容的元数据。比如你要发送多少字节。如果你发送555美元,那么你必须在前面加上前缀:我发送4个字节。您需要有一个能够理解这一点并等待4个字节的侦听器

我在这里引用上面的链接

在第一个接收操作上,接收的字节数少于 前缀 在前一个接收op或ops上具有前缀的接收部分后,然后接收前缀的另一部分,但不接收 所有这些。 在前一个接收op或ops上接收到前缀的一部分后,再接收前缀的其余部分,但仅此而已。 在前一个接收op或ops上接收到部分前缀后,我们将接收其剩余部分,以及部分消息。 在前一个接收op或ops上接收到部分前缀后,我们将接收其剩余部分,以及所有消息。 接收前缀中的字节数,但仅此而已。 在接收到前一个接收操作或操作的前缀中的字节数之后,我们将接收部分字节 信息。 在接收到前一个接收操作或操作的前缀中的字节数之后,我们将接收所有字节 信息。 接收前缀的字节数加上消息的一部分,但不是消息的全部。 在前一个接收op或ops上接收到前缀和消息的一部分后,我们将接收消息的另一部分 信息,但不是全部。 在前一个接收op或ops上接收到前缀和部分消息后,我们将接收消息的所有其余部分 消息 接收前缀的字节数加上第一个接收操作上的所有消息。 最后一种情况实际上是最常见的情况。但是所有的 上述事情可以发生,也确实发生过。如果双方都是客户 服务器的缓冲区大小大于消息,则 当同时运行客户端和 服务器在同一台机器上,甚至在局域网上。但TCP更重要 在数据通过的Internet上不可预测 多台机器。因此,您的代码需要考虑所有这些因素 可能性


您不使用什么流。读取返回。Read可能会一次返回多个数据包或数据包的一半。也不要让catch为空,可能会出现异常!那么我用什么呢,善良的先生?同样,为了调试的目的,把它放在ifcontain$:Console.WriteLine原始数据>>+DataFromClient@PkKingX11,而不是$use\r\n作为分隔符,然后可以使用StreamReader类的ReadLine方法。这样生活会更轻松。这仍然不是一个好的解决方案,他可能会在一个包里拿到99美元,然后在下一个包里拿到8美元999美元。然后你必须加上前缀,不,这只是可以使用的技术之一。分隔字符/字符串也可以使用。例如,twitter的流媒体API使用了新行字符,
        DataFromClient = DataFromClient.Substring(0, DataFromClient.IndexOf("$"));
Okay, so let's think about the possible situations that 
might occur with the data that the server receives in one receive operation: