套接字缓冲区大小:更大与更小的优缺点

socket buffer size: pros and cons of bigger vs smaller

我以前从未真正使用过 COM 套接字,现在有一些代码正在侦听相当稳定的数据流 (500Kb/s - 2000Kb/s)。

我尝试过不同的尺寸,但不太确定我在概念上做什么。

byte[] m_SocketBuffer = new byte[4048];
//vs
byte[] m_SocketBuffer = new byte[8096]; 

我使用的套接字是System.Net.Sockets.Socket,这是我的构造函数:

new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)

我的问题是:

  1. 是否存在大缓冲区与小缓冲区的一般权衡?
  2. 如何确定缓冲区的大小?你应该用什么作为衡量标准?

我正在这样检索数据:

string socketData = Encoding.ASCII.GetString(m_SocketBuffer, 0, iReceivedBytes)
while (sData.Length > 0)
{ //do stuff }
  1. 我的阅读事件是否在缓冲区已满时发生?就像每当套接字缓冲区达到阈值时,我就可以从中读取它?

简短版本:

  • 最佳缓冲区大小取决于很多因素,包括底层网络传输以及您自己的代码如何处理 I/O。
  • 10 的 K 可能适合移动大量数据的大容量服务器。但是,如果您知道远程端点永远不会一次向您发送大量数据,则可以使用更小的数据。
  • 缓冲区在 I/O 操作期间被固定,这可能导致或加剧堆碎片。对于真正的大容量服务器,分配非常大的缓冲区(大于 85,000 字节)可能是有意义的,这样缓冲区是从大对象堆中分配的(没有碎片问题,或者处于永久状态碎片,取决于你如何看待它 :)),然后只使用每个大缓冲区的一部分用于任何给定的 I/O 操作。

回复:您的具体问题:

  1. Is there a general trade-off for large vs. small buffers?

可能最明显的是通常情况:比您实际需要的缓冲区大的缓冲区只是在浪费 space。

使缓冲区太小会强制执行更多 I/O 操作,可能会强制执行更多线程上下文切换(取决于您的操作方式 I/O),并且肯定会增加必须执行的程序语句的数量被执行。

当然还有其他权衡取舍,但对每一个权衡取舍进行讨论对于本论坛而言过于广泛。

  1. How does one go about sizing the buffer? What should you use as a gauge?

我会从看起来 "reasonable" 的尺寸开始,然后从那里进行试验。在各种负载测试场景中调整缓冲区大小,增加和减少,看看是否对性能有影响。

  1. Does my reading event happen when the buffer is full? Like whenever the socket buffer hits the threshold, that's when I can read from it?

当您从套接字读取时,网络层将尽可能多地将数据放入您的缓冲区。如果可用数据多于适合的数据,它将填充缓冲区。如果可用数据少于适合的数据,则操作将在不填充缓冲区的情况下完成(但总是在至少一个字节已放入缓冲区时......读取操作完成零长度的唯一时间是连接正在连接时关闭)