在 Windows 和 Linux 上,SO_SNDBUF 和 SO_RCVBUF 的最小可能大小是多少?是1字节吗?将这些值设置为 1 是否可以达到尽可能小的值?操作系统是否会延迟分配 RAM,直到需要空间为止?
我意识到这会导致数据传输性能很差。我并不是想传输数据。我正在尝试检查服务器是否正在侦听端口,如果没有则标记问题。
在Linux上,SO_RCVBUF的最小值略大于2048,SO_SNDBUF的最小值是SO_RCVBUF最小值的两倍。
Linux 源代码 include/net/sock.h 将最小值定义为:
/* Since sk_{r,w}mem_alloc sums skb->truesize, even a small frame might
* need sizeof(sk_buff) + MTU + padding, unless net driver perform copybreak.
* Note: for send buffers, TCP works better if we can build two skbs at
* minimum.
*/
#define TCP_SKB_MIN_TRUESIZE (2048 + SKB_DATA_ALIGN(sizeof(struct sk_buff)))
#define SOCK_MIN_SNDBUF (TCP_SKB_MIN_TRUESIZE * 2)
#define SOCK_MIN_RCVBUF TCP_SKB_MIN_TRUESIZE
SOCK_MIN_SNDBUF 是最小 SO_SNDBUF,SOCK_MIN_RCVBUF 是最小 SO_RCVBUF。
SOCK_MIN_RCVBUF 的定义是
(2048 + SKB_DATA_ALIGN(sizeof(struct sk_buff)))
,它是 2048 字节加上 L1 缓存对齐的数据包结构的长度。 SO_SNDBUF 的最小值是 SO_RCVBUF
最小大小的两倍。
net/core/sock.c中的
__sock_set_rcvbuf
函数包含一条注释,解释了为什么请求的缓冲区大小加倍,以及为什么在读取大小时返回加倍的大小:
static void __sock_set_rcvbuf(struct sock *sk, int val)
{
/* Ensure val * 2 fits into an int, to prevent max_t() from treating it
* as a negative value.
*/
val = min_t(int, val, INT_MAX / 2);
sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
/* We double it on the way in to account for "struct sk_buff" etc.
* overhead. Applications assume that the SO_RCVBUF setting they make
* will allow that much actual data to be received on that socket.
*
* Applications are unaware that "struct sk_buff" and other overheads
* allocate from the receive buffer during socket buffer allocation.
*
* And after considering the possible alternatives, returning the value
* we actually used in getsockopt is the most desirable behavior.
*/
WRITE_ONCE(sk->sk_rcvbuf, max_t(int, val * 2, SOCK_MIN_RCVBUF));
}
套接字手册页包含以下解释,但最小值不正确:
$ 人 7 插座
SO_SNDBUF
设置或获取最大套接字发送缓冲区(以字节为单位)。这 内核将此值加倍(以留出簿记空间) 当使用setsockopt(2)设置时,开销),并且这个 getsockopt(2) 返回双倍值。默认 值由 /proc/sys/net/core/wmem_default 文件设置 最大允许值由 /proc/sys/net/core/wmem_max 文件设置。 最低(双倍) 该选项的值为 2048。(错误)
SO_RCVBUF
设置或获取最大套接字接收缓冲区(以字节为单位)。当使用setsockopt(2)设置该值时,内核会将该值加倍(以便为簿记开销留出空间),并且该加倍的值由get‐sockopt(2)返回。默认值由 /proc/sys/net/core/rmem_default 文件设置,最大允许值由 /proc/sys/net/core/rmem_max 文件设置。 此选项的最小(双倍)值为 256。(错误)
如果只是您在评论中提到的“每小时数千个端口”,那么您的服务器每小时获得的连接数很可能比您的测试运行程序强加的连接数多一个数量级。只需执行“连接”,然后执行“关闭”即可。其他任何事情都是微观优化。
如果涉及任何类型的代理、端口映射器或负载平衡器,那么测试 TCP 连接本身可能还不够。您可能想要实际测试该套接字上托管的应用程序协议。例如,如果有一个 Web 服务器在端口 8000 上运行,您不仅应该建立 TCP 连接,还应该实际发出 HTTP 请求,并查看是否收到任何类型的响应。