garbage-collection - BeginReceive/SocketAsyncEventArgs ArraySegments 列表

标签 garbage-collection socketasynceventargs beginreceive

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

MSDN for the Socket.BeginReceive constructor甚至没有正确描述第一个参数):

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

Paremeters:
buffers
Type: System.Collections.Generic.IList<ArraySegment<Byte>>
An array of type Byte that is the storage location for the received data.
...

我以为主要思路是在Large Object Heap上分配一个大缓冲区,然后把这个缓冲区的一段传给Socket.BeginReceive ,以避免将小对象固定在堆周围并扰乱 GC 的工作。

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

最佳答案

我在 this question 中发现了什么在 MSDN 中:

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

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

Reads can be multiples of that because if packets arrive out of order all of them are made visible to application the moment the logically first one arrives. You get to read from all contiguous queued packets at once in this case.

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

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

关于garbage-collection - BeginReceive/SocketAsyncEventArgs ArraySegments 列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42699348/

相关文章:

java - 如何针对 vanilla 基准调整 Java GC?

javascript - 网络 worker 有自己的垃圾收集器吗?

javascript - V8如何处理 "large object space"中的对象

.net - begin/end 与 1000 个客户端的 socketasynceventargs

c# - 异步套接字客户端 ReceiveCallback 未执行

haskell - 垃圾收集器如何找出堆栈中的对象引用?

c# - 使用 SocketAsyncEventArgs 编写可扩展的套接字服务器

c# - 如何在异步套接字中接收完整的屏幕截图?

sockets - 是 Socket.BeginReceive(IList<ArraySegment<byte>> 缓冲区.. 不是异步的吗?