4

关于 TPC 连接的“酷”事情之一是数据不会丢失。当数据没有被确认时,TCP应该会重新发送数据。

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

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

这是 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 数据包而不是重新发送数据时?

Socket客户端套接字是这样定义的 AS3 :

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));
4

2 回答 2

4

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

服务器没有回复不正确的 ACK。它用它在流中看到的最后一个字节号的 ACK 进行回复,#119。当服务器在一段时间后未能确认它们时,由客户端重新传输这些丢失的字节。相反,它正在发送 RST。

没有时间信息,但我不得不猜测 RST 来自客户端的超时,然后才重新传输信息。

于 2012-10-12T16:01:30.480 回答
2

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

于 2012-10-12T13:08:00.683 回答