We threw this question to our MS premier techie as we were troubleshooting some related issues and I thought his reply would be helpful for some of you out there.
Q1: What’s the relationship between the TCPWindowSize setting and the DefaultReceiveWindow handled by AFD.sys?
TCPWindowSize defines the amount of receive data (in bytes) that can be buffered during a connection at TCP/IP layer. The sending host can send only that amount of data before it must wait for an acknowledgment and window update from the receiving host. Windows will self-tune the TCP window size if it’s not explicitly defined in registry.
DefaultReceiveWindow defines the default receive buffer in Socket layer. By default, it’s 8 KB. Programs based on Socket gets data from that buffer. When a program receives more data than this buffer is configured to hold, all data received up to this count must be transferred to the program before receiving continues. When this happens, an acknowledgement will be sent to the source machine.
For example, if the application wants to read 32KB from the socket, it actually reads it from the buffer for 4 times (32/8 = 4).
There’s another window called DefaultSendWindow. It defines the default sending buffer in Socket layer at the sender side, which is also 8KB by default. When the data in the buffer has been sent out, afd.sys must wait for the TCP Acknowledgement before sending out the next block.
The relationship varies based on the real situation. In a fast connected network, the default values apply because all packets reach the destination very fast, and the corresponding TCP ACKs go back immediately as well. Buffer is flooded and depleted quickly, and TCP window is always very plentiful.
Problem may happen in a slow network, where the sender may wait for several seconds before receiving the TCP ACK. In that, a bigger TCPWindowSize and DefaultSendWindow may help, as the sender can send out more data without getting the TCP ACK.
Another point deserving consideration is the MTU. In Windows, there’s a feature called “Delayed ACK”. That is, the receiver sends back TCP ACK for every other packet, or after delaying for 200ms. Suppose such a scenario in which the effective MTU between the client and the server is a bit smaller, say, 1290. In that case, the effective MSS is 1290 – 20 (IP header) – 20 (TCP header) = 1250, and 8760/1250 = 7.008. That is, to send out each block, the sender must send out 7 packets.
Considering the mechanism of “Delayed ACK” then. The receiver will send TCP ACK for the 2nd, 4th and 6th packet. However, for the last one 7th packet, it will hold the TCP ACK for 200ms. At the sender side, as described above, it won’t send out the next block before getting the final TCP ACK for the 7th packet. So for each buffer, 200ms is delayed. At that time, we need either tune the network connection to make it support the full MTU of 1500 bytes, or modify the DefaultReceiveWindow and DefaultSendWindow so that each buffer holds even numbers of packets.
Here’re some useful document for you: