我有一个间歇但可重现的TCP连接问题。发件人(端口64613)在Windows机器上运行,而接收器(端口14004)在RedHat 6主机上。端口不是图片的一部分:不同端口也会出现同样的问题。
连接正常工作超过一分钟左右,数据和确认数据包正常流动。
但随后发生以下行为:发送方侧的Wireshark捕获显示正在发送的数据包(seq = 3020828):
57788 2018-07-16 15:36:20.552618000 10.245.40.74 10.245.54.13 TCP 2974 64613 -> 14004 [ACK] Seq=3020828 Ack=73535403 Win=65536 Len=2920
没有收到任何ACK的回复。在最终放弃连接之前,发送方还会在较小的数据包中重新传输最多5次:
58376 2018-07-16 15:36:20.851770000 10.245.40.74 10.245.54.13 TCP 1514 [TCP Retransmission] 64613 -> 14004 [ACK] Seq=3020828 Ack=74313583 Win=1296 Len=1460
58378 2018-07-16 15:36:21.101721000 10.245.54.13 10.245.40.74 TCP 1350 14004 -> 64613 [PSH, ACK] Seq=74313583 Ack=3020828 Win=4096 Len=1296 [TCP segment of a reassembled PDU]
...
60992 2018-07-16 15:36:22.652682000 10.245.40.74 10.245.54.13 TCP 1514 [TCP Retransmission] 64613 -> 14004 [ACK] Seq=3020828 Ack=77762103 Win=1296 Len=1460
60994 2018-07-16 15:36:22.658427000 10.245.54.13 10.245.40.74 TCP 1514 14004 -> 64613 [ACK] Seq=77762103 Ack=3020828 Win=4096 Len=1460 [TCP segment of a reassembled PDU]
...
91947 2018-07-16 15:36:39.456903000 10.245.40.74 10.245.54.13 TCP 54 64613 -> 14004 [RST, ACK] Seq=3022288 Ack=118789563 Win=0 Len=0
接收器侧的tcpcap显示正在接收的数据包(由于中间网络设备,仅在较小的分组中):
13573 2018-07-16 15:36:20.526327000 10.245.40.74 10.245.54.13 TCP 1514 64613 -> 14004 [ACK] Seq=3020828 Ack=73535403 Win=65536 Len=1460
13575 2018-07-16 15:36:20.526360000 10.245.40.74 10.245.54.13 TCP 1514 64613 -> 14004 [ACK] Seq=3022288 Ack=73535403 Win=65536 Len=1460
此外,重传的数据包被正确接收,直到最后的RESET数据包:
13878 2018-07-16 15:36:20.825430000 10.245.40.74 10.245.54.13 TCP 1514 [TCP Retransmission] 64613 -> 14004 [ACK] Seq=3020828 Ack=74313583 Win=1296 Len=1460
18810 2018-07-16 15:36:36.047313000 10.245.54.13 10.245.40.74 TCP 29254 14004 -> 64613 [ACK] Seq=114189103 Ack=3020828 Win=20480 Len=29200 [TCP segment of a reassembled PDU]
...
13991 2018-07-16 15:36:21.425465000 10.245.40.74 10.245.54.13 TCP 1514 [TCP Retransmission] 64613 -> 14004 [ACK] Seq=3020828 Ack=74834803 Win=1296 Len=1460
13993 2018-07-16 15:36:21.433178000 10.245.54.13 10.245.40.74 TCP 27794 14004 -> 64613 [ACK] Seq=74834803 Ack=3020828 Win=4096 Len=27740 [TCP segment of a reassembled PDU]
...
14388 2018-07-16 15:36:22.626436000 10.245.40.74 10.245.54.13 TCP 1514 [TCP Retransmission] 64613 -> 14004 [ACK] Seq=3020828 Ack=77762103 Win=1296 Len=1460
14390 2018-07-16 15:36:22.632029000 10.245.54.13 10.245.40.74 TCP 32174 14004 -> 64613 [PSH, ACK] Seq=77762103 Ack=3020828 Win=4096 Len=32120 [TCP segment of a reassembled PDU]
...
19416 2018-07-16 15:36:39.431628000 10.245.40.74 10.245.54.13 TCP 60 64613 -> 14004 [RST] Seq=3020828 Win=0 Len=0
如上所示,每次接收方回复前一个序列号的ACK消息时:3020828的ACK而不是新的(3020828 + 1460)。
最终,连接下降。
接收器接收新数据包但是为先前的序列号产生ACK的原因是什么?
接收器接收新数据包但是为先前的序列号产生ACK的原因是什么?
我建议收件人(即RedHat系统的应用程序)已停止读取数据。这将填满套接字缓冲区,一旦套接字缓冲区已满,操作系统内核将不再接受任何数据。应用程序仍在通过数据写入原始发件人。但是,由于应用程序读取套接字缓冲区已满,因此套接字缓冲区中最后一个(仍未读取)数据的ACK将与写入原始发送方的数据一起发送。