关于 TCP window size

原创
2014/05/13 09:55
阅读数 4.5W

今天发现IM的发送大量消息的TCP报文里有很多

524 22.770505000 192.168.1.26 192.168.2.203 TCP 60 [TCP ZeroWindow] xmpp-client → 18723 [ACK] Seq=1622 Ack=7849 Win=0 Len=0

Window size value: 0

【Calculated window size: 0】

Window size scaling factor: 128

特别查了下做个记录,

window size 官方定义是:在未收到对方确认报文时,发送端能发送的字节(八字节)数;

作用看这个动画:http://histrory.visualland.net/tcp_swnd.html


The easiest way to understand TCP Window size is to observe two people having a conversation. Every so often, the talker will wait for the listener to acknowledge that they have heard everything up to that point. Once the listener acknowledges then the talker begins to talk again. The amount of words spoken before waiting for an acknowledgement from the listener is much like the TCP window size. The official definition of the window size is "the amount of octets that can be transmitted without receiving an acknowledgement from the other side".


Let's assume that the receiver window size is 16,384 bytes which means that the sender can send up to 16,384 bytes before stopping to wait for an acknowledgement. Let's also assume that the maximum segment size is 1024. This means that the sender can send 1024 bytes 16 times before it will stop sending and wait for an acknowledgement. For the sake of simplicity, I will not discuss TCP slow start (Rapid Increase/Multiplicative Decrease), congestion avoidance, congestion window and congestion control etc. As a side note keep in mind that the sender rate is controlled by the min(congestion window, receive window).


So what is the optimum window size that two hosts should agree on? Well there are different school of thoughts, but let's look at one example where the window size is 2 x BDP. What the heck is  BDP you ask? BDP is short for  bandwidth-delay product. Here is how to calculate BDP. Bandwidth times one-way latency.

For example take two hosts connected with 20 Mbps of bandwidth and using PING/ICMP we conclude that the  one-way latency is 20 ms. First let's convert 20 Mbps into bytes which turns out to be  2,621,440 bytes. Take 2,621,440 x .02 equals to approximately 52,428. So 2 x 52,428 =   104,856 bytes, therefore the  optimum window size for 2 hosts with 20 Mbps of bandwidth with a 20 ms one-way latency is 104,856 bytes. That is the sender can send 104,856 bytes of data before the sender must wait for an acknowledgement from the receiver. The reason we are doing 2 x the BDP is because the sender does not have to wait the time it takes for the ACK from the receiver (that he got the first 52428 bytes of data) to come back to the sender. Instead of the sender sitting IDLE for the ACK to come back, the sender can use the ACK travel time (20 ms) to actually send another 52,428 bytes of data.

One problem, the TCP RFC states that the  window size is a  16 bit field which means that the largest window size that can be advertised is 65,536 or 2 ^ 16 or 1111 1111 1111 1111 (16 bits). And as we saw earlier, it is optimum to use 104,856 for the window size. So how do we accomplish this? This is where  window scaling comes into play. It is a TCP option that is sent with the initial TCP 3 way handshake and both sides MUST agree to use this option or else window scaling will not be used. Window scaling basically  bitwise shifts the window size. So let's take a look at a wireshark packet capture to further explain this. Note that window scale option/shift count will be  only be sent/negotiated in the initial 3 way handshake  (SYN, SYN-ACK,ACK).


Flags 0x002 (SYN) - Initial SYN Packet sent by the sender.
Window size value: 8192 or 0010 0000 0000 0000 (16 bits).
Window scale Shift count: 8 - bit-wise shift window size by 8 to the left.
Window multiplier: 256 or 2 ^ shift count which is 2 ^ 8 in this case.


Flags 0x012 (SYN,ACK) - SYN, ACK packet sent by the receiver acknowledging the initial SYN packet.
Window size value: 5840 or 0001 0110 1101 0000 (16 bits).
Window scale Shift count: 7 - bit-wise shift window size by 7 to the left.
Window multiplier: 128 or 2 ^ shift count which is 2 ^ 7 in this case.


Now we are inspecting a packet farther down the conversation. This is a packet sent by 192.168.1.78 who notified the other end to use a shift count of 8.

Window size value: 64 or 0000 0000 0100 0000 (16 bits)
Window size scaling factor: 256 or 2 ^ 8 (as advertised by the 1st packet)
Although the window size states 64, the actual window size is 16,384 (64 * 256) meaning that the other side can send 16,384 bytes of data before stopping to wait for an acknowledgement.

As the conversation between the two hosts continue, the  window size can be narrowed or widen using the widow sizeby specifying the window size value in the 16 bit field however the  window size scaling factor must/will remains the same. For example if the sender wants to make the window size 104,856 the window size would be set as 410 in the 16 bit option field. 

410 or 0000 0001 1001 1010 (16 bits) and since it will be shifted 8 to the left, the actual window size will be 104,960 or 0000 0000 0000 0001 1001 1010 0000 0000 (32 bits).

The maximum number of the shift count is 14 per  RFC 1323 which means that the maximum window size can be 1 gigabyte. That is ONE BIG window size!!


Many more articles to come so stay tuned.

Please subscribe/comment/+1 if you like my posts as it keeps me motivated to write more and spread the knowledge.

参考:http://ithitman.blogspot.com/2013/02/understanding-tcp-window-window-scaling.html





linux的window size

How many of you have notice that no matter you have a 100 Mb line, you only get near 2 Mbps, well that is because the TCP window size is only of 32 kB or 64 kB on Linux (depends

on distribution) and 8 kB on M$ Windows.

The TCP window size is the amount of data that will be send on aconnection before a host stops and waits for an acknowledgment. This is used by TCP to prevent congestion.

Ideally it should be:


  Window size = Bandwidth x round trip time



#cd /proc/sys/net/core
#ls
message_burst    netdev_max_backlog    rmem_default    wmem_default
message_cost    optmem_max    rmem_max    wmem_max
-------
(The secret are on these files)
/proc/sys/net/core/rmem_default   - default receive window
/proc/sys/net/core/rmem_max       - maximum receive window
/proc/sys/net/core/wmem_default  - default send window
/proc/sys/net/core/wmem_max      - maximum send window

展开阅读全文
打赏
0
4 收藏
分享
加载中
更多评论
打赏
0 评论
4 收藏
0
分享
返回顶部
顶部