我有一个用C ++编写的小型Android应用程序,它打开一个TCP套接字到我的HTTP服务器(python -m SimpleHTTPServer
)并发送一个标头。没有进一步配置,这是设备发送的SYN:
Transmission Control Protocol, Src Port: 47262 (47262), Dst Port: 8000 (8000), Seq: 0, Len: 0
Source Port: 47262
Destination Port: 8000
[Stream index: 47]
[TCP Segment Len: 0]
Sequence number: 0 (relative sequence number)
Acknowledgment number: 0
Header Length: 40 bytes
Flags: 0x002 (SYN)
Window size value: 65535
[Calculated window size: 65535]
Checksum: 0x54cb [validation disabled]
Urgent pointer: 0
Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
Maximum segment size: 1460 bytes
TCP SACK Permitted Option: True
Timestamps: TSval 3637366, TSecr 0
No-Operation (NOP)
Window scale: 7 (multiply by 128)
窗口大小为65,535,窗口缩放系数为7,因此客户端隐含地说其接收缓冲区为65,535 * 2 ^ 7 = 8,388,480。
现在,我在代码中添加以下行:
unsigned long receive_buffer_size = 65535*127;
res = setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &receive_buffer_size, sizeof(receive_buffer_size));
在使用socket()
打开套接字之后,但在使用connect()
将其连接到端口之前,会出现这些行。
我认为这不会影响接收缓冲区,因为我们提供的值与默认设置的值相同。但是,结果如下:
Transmission Control Protocol, Src Port: 47263 (47263), Dst Port: 8000 (8000), Seq: 0, Len: 0
Source Port: 47263
Destination Port: 8000
[Stream index: 2]
[TCP Segment Len: 0]
Sequence number: 0 (relative sequence number)
Acknowledgment number: 0
Header Length: 40 bytes
Flags: 0x002 (SYN)
Window size value: 65535
[Calculated window size: 65535]
Checksum: 0xcf44 [validation disabled]
Urgent pointer: 0
Options: (20 bytes), Maximum segment size, SACK permitted, Timestamps, No-Operation (NOP), Window scale
Maximum segment size: 1460 bytes
TCP SACK Permitted Option: True
Timestamps: TSval 3698768, TSecr 0
No-Operation (NOP)
Window scale: 5 (multiply by 32)
接收缓冲区已降至65,535 * 2 ^ 5 = 2,097,120。这怎么解释?
在设置参数之前和之后,我正在使用以下行编写SO_RCVBUF:
res = getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &curr_value, &optlen);
在设置参数之前,SO_RCVBUF是1,048,576 - 远不及我们在第一个snif中看到的默认值。之后,它是2,097,152,这不是我使用setsockopt()
提供的。最后一个数字与我们在第二个snif中看到的数量级相同,所以至少在那里有一些一致性。
请注意,对于每次通话,res
均为正,因此getsockopt()
和setsockopt()
始终成功。
我可以理解操作系统维持设置SO_RCVBUF的限制,但为什么它低于默认值?为什么在设置任何值之前读取SO_RCVBUF会导致值低于默认值?
答案 0 :(得分:3)
SYN段的实际窗口大小不适用于缩放。例如。它等于你的例子中的65535,而不是你计算的8,388,480。这是因为客户端还不知道接收方是否支持窗口缩放。窗口缩放字段的作用类似于发送方支持窗口缩放的通知,并且其他段的窗口大小必须计算为window_size<<window_scale
。
示例:
因此,您需要查看更多细分以找出实际的窗口大小。