3

传递to /列表背后的原因是什么?ArraySegment<byte>Socket.BeginReceiveSocketAsyncEventArgs

Socket.BeginReceive构造函数的 MSDN甚至没有正确描述第一个参数):

public IAsyncResult BeginReceive(
    IList<ArraySegment<byte>> buffers,
    SocketFlags socketFlags,
    AsyncCallback callback,
    object state
)

参数:
buffers
类型:类型System.Collections.Generic.IList<ArraySegment<Byte>>
数组Byte,是接收数据的存储位置。
...

我认为主要的想法是在大对象堆上分配一个大缓冲区,然后将这个缓冲区的一部分传递给Socket.BeginReceive,以避免将小对象钉在堆周围并弄乱 GC 的工作。

但是为什么我要向这些方法传递几个段呢?如果是SocketAsyncEventArgs,似乎会使这些对象的池化复杂化,我看不出这背后的原因。

4

1 回答 1

1

我在这个问题和 MSDN 中发现了什么:

  1. 有一个重载版本BeginReceive需要一个字节数组。当它已满或已接收到数据包(逻辑上按顺序)时,将触发回调。

  2. 如我链接的答案中所述:

读取可以是它的倍数,因为如果数据包无序到达,则在逻辑上第一个到达的那一刻,所有这些都对应用程序可见。在这种情况下,您可以一次读取所有连续排队的数据包。

这意味着:如果有一个乱序的传入数据包(即序列号比预期的更高),它将被保留。一旦丢失的数据包到达,所有可用的数据包都会写入您的列表,并且只会触发一个回调,而不是为所有可用的数据包一遍又一遍地触发回调,每个数据包都尽可能地填充您的缓冲区,依此类推.

这意味着,此实现通过在数组列表中提供所有可用数据包仅调用回调一次而不是从网络堆栈到缓冲区执行大量内存复制并重复调用回调,从而节省了大量开销。

于 2017-03-19T22:24:31.830 回答