我正在一个非常有限的网络设备上编写一个 HTTP 服务器,该设备使用 uIP 1.0 作为 TCP/IP 堆栈。该库不缓冲任何数据,它仅调用用户回调来提供要发送的单个数据包或重新发出先前的数据以进行重传。下一个数据包在前一个数据包被远程端确认后发送。我的服务器发送的第一个数据包是响应标头(45 字节),然后文件以 846 字节的块形式发送。问题是远程端(macos 或 Linux、firefox 或 wget)从第三个数据包开始停止发送 ACK。由于没有收到任何 ACK,我的设备开始重新传输该数据包并最终重置连接。每次都会以完全相同的方式发生这种情况。如果我将数据分成较小的块(例如,每个块 256 字节),则在 ACK 停止到来之前会收到更多数据包 - 大约 10 个而不是 3 个。
这是一个会话的转储,转储是使用wireshark在客户端站点(192.168.178.30)上执行的:
1 0.000000 192.168.178.30 192.168.178.70 TCP 78 56391 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=64 TSval=3618183324 TSecr=0 SACK_PERM
2 1.001115 192.168.178.30 192.168.178.70 TCP 78 [TCP Retransmission] 56391 → 80 [SYN] Seq=0 Win=65535 Len=0 MSS=1460 WS=64 TSval=3618184325 TSecr=0 SACK_PERM
3 1.096615 192.168.178.70 192.168.178.30 TCP 1008 80 → 56391 [SYN, ACK] Seq=0 Ack=1 Win=846 Len=0 MSS=846
4 1.097032 192.168.178.30 192.168.178.70 TCP 54 56391 → 80 [ACK] Seq=1 Ack=1 Win=65535 Len=0
5 1.125337 192.168.178.30 192.168.178.70 TCP 192 56391 → 80 [PSH, ACK] Seq=1 Ack=1 Win=65535 Len=138
6 1.447170 192.168.178.70 192.168.178.30 TCP 1008 80 → 56391 [PSH, ACK] Seq=1 Ack=139 Win=846 Len=45
7 1.447485 192.168.178.30 192.168.178.70 TCP 54 56391 → 80 [ACK] Seq=139 Ack=46 Win=65535 Len=0
8 1.754454 192.168.178.70 192.168.178.30 TCP 1008 80 → 56391 [PSH, ACK] Seq=46 Ack=139 Win=846 Len=846
9 1.754807 192.168.178.30 192.168.178.70 TCP 54 56391 → 80 [ACK] Seq=139 Ack=892 Win=65535 Len=0
10 2.061660 192.168.178.70 192.168.178.30 TCP 1008 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
11 2.794855 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
12 3.597716 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
13 4.645639 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
14 6.567428 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
15 9.844375 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
16 15.988703 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
17 22.132761 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
18 28.277190 192.168.178.70 192.168.178.30 TCP 1008 [TCP Retransmission] 80 → 56391 [PSH, ACK] Seq=892 Ack=139 Win=846 Len=846
19 34.318832 192.168.178.70 192.168.178.30 TCP 1008 80 → 56391 [RST, ACK] Seq=892 Ack=139 Win=846 Len=0
未收到 ACK 的数据包的 TCP 校验和不正确。 Wireshark默认不验证TCP校验和,这就是为什么我没有注意到这个问题。