SO_SNDBUF的影响

我无法理解以下代码段的工作方式和原因:

/* Now lets try to set the send buffer size to 5000 bytes */ size = 5000; err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(int)); if (err != 0) { printf("Unable to set send buffer size, continuing with default size\n"); } 

如果我们检查发送缓冲区的值,它确实正确设置为5000 * 2 = 10000。但是,如果我们尝试发送超过发送缓冲区大小,它发送所有的。 例如:

  n = send(sockfd, buf, 30000, 0); /* Lets check how much us actually sent */ printf("No. of bytes sent is %d\n", n); 

这打印出30000。

这是如何工作的? 发送缓冲区大小限制为10000的事实是否有影响? 如果是的话,到底发生了什么? 某种碎片?

更新:如果套接字处于非阻塞模式会发生什么? 我尝试了以下内容:

  1. 将缓冲区大小更改为10000(5000 * 2)将导致发送16384个字节
  2. 将缓冲区大小更改为20000(10000 * 2)将导致发送30000字节

再一次,为什么?

对于TCP和UDP,设置SO_SNDBUF选项的效果是不同的。

  • 对于UDP,它设置数据报大小限制 ,即任何更大的数据将被丢弃。
  • 对于TCP,这只是为给定的套接字设置内核缓冲区的大小(对页面边界进行一些四舍五入并具有上限)。

由于它看起来像是在谈论TCP,因此您观察到的效果可以通过套接字处于阻塞模式来解释,因此send(2)阻塞,直到内核可以接受您的所有数据,并且/或者网络堆栈异步出队数据并将其推送到网卡,从而释放缓冲区中的空间。

此外,TCP是一个流协议 ,它不保留任何“消息”结构。 一个send(2)可以对应于另一方的多个recv(2) 。 将其视为字节流。

SO_SNDBUF配置套接字实现在内部使用的缓冲区。 如果您的套接字是非阻塞的,则只能发送到配置的大小,如果您的套接字被阻塞,则对您的呼叫没有限制。