我如何在网络流中写出一个小差距?

时间:2018-05-27 16:55:12

标签: c# server networkstream pause

我有一台服务器通过NetworkStream向接收者发送不同大小的遥测数据,或者我称之为客户端。我的目标是最大速度,所以我想要最小的延迟。频率是不受控制的,所以我想在我的客户端使用无限循环,使用NetworkStream.Read来读取数据,处理数据,然后重复。

我的问题是,有时,如果两个数据包发送速度非常快,而客户端连接速度较慢,则这两个数据包将作为连续数据流接收,从而导致无法处理的数据。我找到的半解决方案(主要是为了确认这确实是错误)是在每次传输之后/之前有一个小的延迟,使用System.Threading.Thread.Sleep(100),但不仅我发现Sleep一个僵化的解决方案,它是不一致的,因为它也会使连接良好的客户端变慢,并且问题可能会持续存在更糟糕的连接。

我想要做的是让服务器在每次传输之间发送间隙,无论互联网速度如何都提供分离,因为NetworkStream.Read应在当前连续流结束后完成。我不太了解NetworkStream的工作情况,也不知道空流的几个字节是什么样的,或者它是如何实现的。有什么想法吗?

2 个答案:

答案 0 :(得分:4)

如果可能的话,我强烈建议改变协议。 TCP 基于流的协议,任何有效忽略该协议的尝试都可能不可靠。

相反,我建议更改为使其成为消息流,其中每条消息都有一个前缀,指示消息正文的长度。这样,如果特定消息被分割为多个分组或者在与其他消息相同的分组中接收,则无关紧要。它还使客户更容易阅读:他们确切地知道要读取多少数据,因此可以在一个简单的循环中完成。

如果您担心长度前缀会引入太多开销(如果数据通常很小),则可能会使包含整批信息(多个遥测项目)的单个消息使协议稍微复杂一些。

但从根本上说,值得假设数据分成多个数据包,再次组合等。不要假设一个写操作对应于一个读操作。

答案 1 :(得分:1)

您没有特别提及您在ProtocolType上使用的NetworkStream,但TCP必然会使您的要求失败。中间路由器/交换机无法知道您的意图是按时间分离数据包并且不会尊重该期望。此外,面向流的TCP按顺序传送数据包,并且对丢弃的数据包和损坏的数据包进行纠错。在任何一个或另一个出现时,它将保留所有其他数据包,直到重新发送错误数据包 - 然后你可能会将它们全部收集起来。

使用UDP并在接收(即客户端)方面实施限制 - 如果您落后,则丢弃数据。