2013-10-29 58 views
0

已知getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &opt_val, &opt_len);返回在setsockopt()之前分配的tcp缓冲区大小的两倍。TCP缓冲区中的包总长度是否可以超过分配的缓冲区大小?

(写在man 7 tcp

Note that TCP actually allocates twice the size of the buffer requested in the setsockopt(2) call, and so a succeeding getsockopt(2) call will not return the same size of buffer as requested in the setsockopt(2) call. TCP uses the extra space for administrative purposes and internal kernel structures,

所以,如果我为buf_size = 256Ksetsockopt(sock, SOL_SOCKET, SO_SNDBUF, (int *)&buf_size, sizeof(buf_size))512K将被分配在getsockopt()返回。

我想计算tcp buffer的当前字节数。因为我正在计数队列中每个数据包的长度(sk->sk_write_queue->len),而skstruct sock *sk

发生的情况有时候返回的长度大于256K。 (例如,我得到294879字节,即32735字节多于256K)。

为什么会发生? 是否包含"extra space for administrative purposes and internal kernel structures"作为getsockopt(.., SOL_SOCKET, SO_SNDBUF, ..)

谢谢。

回答

2

由于512K实际上被分配,所以缓冲294879字节并不令人惊讶。 在linux上,当你设置SO_SNDBUF时,内核只需加倍这个数量。

如果您希望套接字缓冲区为256k,请用128k调用setsockopt()。

现在,所使用的缓冲区并非纯粹用于您的数据,skb和其他内核需要的数据结构在这些缓冲区中分配,这就是“管理开销”,这相当于多少开销取决于内核将您提供的数据切片 - 因此,仅为您从用户空间发送的数据准确地预留256k的缓冲空间是一项相当困难的任务,如果不是几乎不可能的话。

+0

谢谢,那么返回的长度不包含任何“管理开销”?只有数据本身? – hudac

+0

@hudac我相信这只是用户数据,尽管它肯定取决于你如何计算协议栈中的长度和位置。 – nos

+0

另请注意,您可以在TCP套接字上执行SIOCOUTQ ioctl(),该套接字应该为您提供TCP套接字缓冲区中的字节数量(这将是尚未发送的数据量+发送的数据量由同行承认) – nos