关于 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));