为什么TCP套接字在收到错误的ACK时发送RST数据包而不是重发数据?

时间:2012-10-12 13:04:01

标签: c++ actionscript-3 sockets tcp tcpdump

关于TPC连接的一个“酷”事情是数据不会丢失。当数据未被确认时,TCP 据称重新发送数据。

我有一个用c ++编写的经典游戏服务器,客户端是用Flash AS3编写的。

在客户端,我添加了一个检查工具,每隔X秒尝试连接到YouTube和Twitter,超时为5秒。问题是,在客户端的Internet连接在几秒钟内断开(Internet检查器收到1或2个超时,但在收到OK后),它开始从服务器接收数据,但服务器停止从客户端接收数据。 / p>

这是TCPDUMP收到的流程:

1. server > client: Flags [P.], seq 2374:2378, ack 119, win 14600, length 4
2. client > server: Flags [.], ack 2374, win 15524, length 0
3. client > server: Flags [.], ack 2378, win 15520, length 0
 . [Here the client sends data to the server, but the server never receives it...]
4. server > client: Flags [P.], seq 2378:2383, ack 119, win 14600, length 5
5. server > client: Flags [P.], seq 2386:2389, ack 119, win 14600, length 3
6. client > server: Flags [.], ack 2386, win 15512, length 0
7. client > server: Flags [.], ack 2389, win 15509, length 0
8. client > server: Flags [R.], seq 127, ack 2389, win 0, length 0

正如您所读到的,当服务器发送带有错误ACK的数据时,客户端不会重新发送数据,而是发送RST数据包(强制服务器关闭连接)。在客户端日志中,我可以看到接收并处理服务器发送的数据(因此,当服务器发送错误的ACK时,连接不会关闭)。

当TCP在收到错误的ACK后决定发送RST数据包而不是重发数据时?

客户端套接字是以这种方式定义的AS3 Socket

var socket:Socket = new Socket();

服务器套接字使用fcntl()设置为非阻塞。也有这个选项:

setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char *)&dummyint, sizeof(int));
setsockopt(socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&dummyint, sizeof(int));

2 个答案:

答案 0 :(得分:4)

请注意,转储中似乎缺少一个额外的数据包,服务器字节为2383-2385,但似乎客户端确实看到了它们,因为它确认了它们。

服务器未回复错误的ACK。它回复了它在流#119中看到的最后一个字节数的ACK。当服务器在一段时间后无法确认它们时,由客户端重新传输那些丢失的字节。相反,它正在发送RST。

没有时间信息,但我不得不猜测RST是在客户端超时之前发出的,因此需要重新发送信息。

答案 1 :(得分:2)

TCP本身并不“不稳定”,它是一种协议。如果有什么不稳定,那就是你的网络连接。 TCP具有在不稳定网络上重试的算法。您的代码也可能出现问题,并且可能会有中间设备超时连接。