windows 什么是 SO_SNDBUF 和 SO_RCVBUF

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4257410/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 07:46:16  来源:igfitidea点击:

What are SO_SNDBUF and SO_RCVBUF

windowssocketsnetwork-programming

提问by Hex

Can you explain me what exactly are SO_SNDBUFand SO_RCVBUFoptions?

你能解释一下到底是什么SO_SNDBUFSO_RCVBUF选项吗?

OK, for some reason the OS buffers the outgoing/incomming data but I'd like to clarify this subject.

好的,出于某种原因,操作系统缓冲传出/传入数据,但我想澄清这个主题。

  • What is their role (generally)?
  • Are they per-socket buffers?
  • Is there a connection between Transport layer's buffers (the TCP buffer, for example) and these buffers?
  • Do they have a different behaviour/role when using stream sockets (TCP) and when using connectionless sockets (UDP)?
  • 他们的角色(一般)是什么?
  • 它们是每个套接字缓冲区吗?
  • 传输层的缓冲区(例如 TCP 缓冲区)和这些缓冲区之间是否存在连接?
  • 在使用流套接字 (TCP) 和使用无连接套接字 (UDP) 时,它们是否具有不同的行为/角色?

A good article will be great too.

一篇好文章也会很棒。

I googled it but didn't find any useful information.

我用谷歌搜索但没有找到任何有用的信息。

回答by DS.

The "SO_" prefix is for "socket option", so yes, these are per-socket settings for the per-socket buffers. There are usually system-wide defaults and maximum values.

“SO_”前缀用于“套接字选项”,所以是的,这些是每个套接字缓冲区的每个套接字设置。通常有系统范围的默认值和最大值。

SO_RCVBUFis simpler to understand: it is the size of the buffer the kernel allocates to hold the data arriving into the given socket during the time between it arrives over the network and when it is read by the program that owns this socket. With TCP, if data arrives and you aren't reading it, the buffer will fill up, and the sender will be told to slow down (using TCP window adjustment mechanism). For UDP, once the buffer is full, new packets will just be discarded.

SO_RCVBUF更容易理解:它是内核分配的缓冲区大小,用于在数据通过网络到达和被拥有该套接字的程序读取之间的时间段内保存到达给定套接字的数据。使用 TCP,如果数据到达而您没有读取它,缓冲区将填满,并且发送方将被告知放慢速度(使用 TCP 窗口调整机制)。对于 UDP,一旦缓冲区已满,新数据包将被丢弃。

SO_SNDBUF, I think, only matters for TCP (in UDP, whatever you send goes directly out to the network). For TCP, you could fill the buffer either if the remote side isn't reading (so that remote buffer becomes full, then TCP communicates this fact to your kernel, and your kernel stops sending data, instead accumulating it in the local buffer until it fills up). Or it could fill up if there is a network problem, and the kernel isn't getting acknowledgements for the data it sends. It will then slow down sending data on the network until, eventually, the outgoing buffer fills up. If so, future write()calls to this socket by the application will block (or return EAGAINif you've set the O_NONBLOCKoption).

SO_SNDBUF,我认为,只对 TCP 重要(在 UDP 中,您发送的任何内容都直接发送到网络)。对于 TCP,如果远程端没有读取,您可以填充缓冲区(这样远程缓冲区变满,然后 TCP 将此事实传达给您的内核,您的内核停止发送数据,而是将其累积在本地缓冲区中,直到它填上)。或者,如果存在网络问题,并且内核没有收到它发送的数据的确认,它可能会填满。然后它会减慢在网络上发送数据的速度,直到最终传出缓冲区填满为止。如果是这样,write()应用程序以后对该套接字的调用将被阻止(EAGAIN如果您设置了该O_NONBLOCK选项,则返回)。

This all is best described in the Unix Network Programmingbook.

这一切在Unix 网络编程一书中得到了最好的描述。

回答by user2066241

In Windows, the send buffer does have an effect in UDP. If you blast packets out faster than the network can transmit them, eventually you will fill the socket output buffer and SendTo will fail with "would block". Increasing SO_SNDBUF will help with this. I had to increase both the send and receive buffers for a test I was doing to find the maximum packet rate I could send between a Windows box and a Linux box. I could have also handled the send size by detecting the "would block" error code, sleeping a bit, and retrying. But pumping up the send buffer size was simpler. The default in Windows is 8K, which seems needlessly small in this era of PC's with GB's of RAM!

在 Windows 中,发送缓冲区在 UDP 中确实有影响。如果您将数据包发送出去的速度比网络传输它们的速度快,最终您将填满套接字输出缓冲区,而 SendTo 将失败并显示“将阻塞”。增加 SO_SNDBUF 将对此有所帮助。我必须增加发送和接收缓冲区以进行测试,以找到我可以在 Windows 机器和 Linux 机器之间发送的最大数据包速率。我还可以通过检测“会阻止”错误代码、稍微休眠并重试来处理发送大小。但是增加发送缓冲区大小更简单。Windows 中的默认值是 8K,在这个拥有 GB 内存的 PC 时代,这似乎太小了!

回答by Len Holgate

Searching Google for "SO_RECVBUF msdn" gave me...

在 Google 上搜索“SO_RECVBUF msdn”给了我...

http://msdn.microsoft.com/en-us/library/ms740476(VS.85).aspx

http://msdn.microsoft.com/en-us/library/ms740476(VS.85).aspx

which answers your "are they per socket" with these lines from the options table:

用选项表中的这些行回答您的“它们是每个套接字吗”:

SO_RCVBUF int Specifies the total per-socket buffer space reserved for receives.
SO_SNDBUF int Specifies the total per-socket buffer space reserved for sends.

With more detail later on:

稍后会详细介绍:

SO_RCVBUF and SO_SNDBUF

When a Windows Sockets implementation supports the SO_RCVBUF and SO_SNDBUF options, an application can request different buffer sizes (larger or smaller). The call to setsockopt can succeed even when the implementation did not provide the whole amount requested. An application must call getsockopt with the same option to check the buffer size actually provided.

SO_RCVBUF 和 SO_SNDBUF

当 Windows 套接字实现支持 SO_RCVBUF 和 SO_SNDBUF 选项时,应用程序可以请求不同的缓冲区大小(更大或更小)。即使实现没有提供请求的全部数量,对setsockopt 的调用也可以成功。应用程序必须使用相同的选项调用getsockopt 来检查实际提供的缓冲区大小。

回答by Guangtong Shen

Above answers didn't answer all questions, especially about the relationship between Socket buffer and TCP buffer.

以上答案并没有回答所有问题,特别是关于 Socket 缓冲区和 TCP 缓冲区之间的关系。

I think they are different things in different layer. TCP buffer is the consumer of Socket buffer.

我认为它们是不同层次的不同事物。TCP 缓冲区是 Socket 缓冲区的消费者。

Socket buffers (input & output) is an IO buffer that is accessed by System calls from the application code in user space. For example, with output buffer, the application code can

套接字缓冲区(输入和输出)是一个 IO 缓冲区,由用户空间中的应用程序代码的系统调用访问。例如,使用输出缓冲区,应用程序代码可以

  • Send data immediately before the buffer is full and be blocked when buffer is full.
  • Set the buffer size.
  • Flush the data in buffer to the underlying storage (TCP send buffer).
  • Close the output buffer by close the stream.
  • 在缓冲区满之前立即发送数据,并在缓冲区满时被阻塞。
  • 设置缓冲区大小。
  • 将缓冲区中的数据刷新到底层存储(TCP 发送缓冲区)。
  • 通过关闭流来关闭输出缓冲区。

TCP buffers (send & receive) are in kernel space that only OS can access. For example, with TCP send buffer, the TCP protocol implementation can

TCP 缓冲区(发送和接收)位于内核空间,只有操作系统才能访问。例如,使用 TCP 发送缓冲区,TCP 协议实现可以

  • Send packets and accept ACK.
  • Guarantee delivery and ordering of packets.
  • Control congestion by resizing the inflight packets window.
  • 发送数据包并接受 ACK。
  • 保证数据包的交付和订购。
  • 通过调整传输中数据包窗口的大小来控制拥塞。

By the way, UDP protocol doesn't have buffer but UDP socket can still have IO buffer.

顺便说一下,UDP 协议没有缓冲区,但 UDP 套接字仍然可以有 IO 缓冲区。

These are my understanding and I'm more than happy to get any feedback/modification/correction.

这些是我的理解,我很高兴得到任何反馈/修改/更正。