我有一个使用SocketAsyncEventArgs异步接收UDP数据包的标准实现。我从docs和一些googling中无法理解的是,我是否应该在回调本身中处理消息,比如在我所指的完整实现中的此评论表示,或者我应该将处理卸载到其他线程,例如通过ConcurrentQueue或BlockingCollection。
我所关注的问题如下:
那么,使用SocketAsyncEventArgs处理消息以确保丢失最少的数据报、不对回调呼叫进行额外重新排序和不增加延迟的最佳实践或预期的方法是什么?
还有一个相关的问题-- ReceiveAsync是否保证有任何订单,或者至少尝试按照从网络接收包的相同顺序调用回调,还是应该使用阻塞接收?目标用例是订阅6-8个UDP通道,其中每个通道的顺序非常重要。运行许多阻塞线程看起来比处理回调要复杂得多,但如果只有这样的解决方案才能保证消息顺序,那么就不那么困难了。
发布于 2017-07-16 21:39:21
使用SocketAsyncEventArgs处理消息以确保尽可能少丢失数据报的最佳实践或预期方法是什么?
坦率地说,这在某种程度上是一个意见问题,也非常依赖于你的确切情况。作为一般规则,您的I/O完成例程应该是快速的。如果您的处理速度很快,那么在例程中这样做是可以的。如果没有,您应该尽可能少地做工作,即将数据移动到可以在其他地方处理的队列,然后从完成例程返回。
记住,“快”在这里是相对的。你只需要比网络更快,尽管网络速度不断提高,在现代CPU上做起来并不难。网络层将代表您进行缓冲,因此假设您的工作负载吞吐量大于网络上的吞吐量,那么在完成例程中执行该工作可能是很好的。
但实际上,这取决于。一般地说哪一个更好是没有办法的。每个特定的场景都是不同的。
ReceiveAsync是否保证有任何订单,或者至少尝试按照从网络接收包的相同顺序调用回调,或者我应该使用阻塞接收来实现这一点?
封锁接收不会有帮助的。
异步方法都有相同的特性:您可以一次发出多个,并且它们将按照发出它们的相同顺序完成。但是,您仍然需要跟踪发出读取操作的顺序。缓冲区将按照您给网络层的顺序填充,但是完成例程可能会被无序执行,因为它们是在线程上执行的,而线程调度程序并不保证线程执行的顺序。仅仅因为一个线程在另一个线程之前就可以运行,这并不意味着它实际上会在另一个线程之前得到它的下一个线程。
但实际上更糟的是:
目标用例是订阅6-8个UDP通道,其中每个通道的顺序非常重要。
如果顺序在您的场景中很重要,您需要在您的数据报中包含序列号,并确保在收到这些数据报时使用这些序列号将数据按正确的顺序排列。
UDP不能保证订购。数据报可按任何顺序接收,而不论其发送顺序如何。UDP也根本不保证交付。数据报可以随时丢弃。UDP也不能保证唯一性。给定的数据报可以多次传递。
如果在您的场景中可靠性和排序很重要,那么您可能应该使用TCP,而不是UDP。
如果您只关心订购,那么UDP可能仍然适用于您。在这种情况下,由于您无论如何都需要数据报中的序列号,所以它确实使“多个并发读取操作”场景更简单,因为数据本身带有序列号,因此不需要单独跟踪它(例如,在与每个读取操作相关联的状态对象中)。
https://stackoverflow.com/questions/45133069
复制相似问题