为什么RST包不需要TIME_WAIT状态?
Why does the RST packet not need the TIME_WAIT state?
我知道 TIME_WAIT
是为了防止一个连接的延迟段被误解为后续连接的一部分。在连接处于 TIME_WAIT 等待状态时到达的任何段都将被丢弃。
在我的实验中,当客户端发送 RST 数据包而不是 FIN 数据包时,我看不到 TIME_WAIT
。为什么?
服务器
while (1) {
int len = sizeof(struct sockaddr);
fd = accept(sfd, &remote, &len);
read(fd, buf, sizeof(buf));
strcpy(buf, "Hello Client");
write(fd, buf, strlen(buf));
close(fd);
}
客户端
res = connect(sfd, result->ai_addr, result->ai_addrlen);
strcpy(buf, "Hello Server!");
write(sfd, buf, strlen(buf));
close(sfd);
注意:客户端发送 RST 而不是 FIN,因为它在关闭套接字之前不读取服务器已经发送的缓冲数据。
因为它声明不存在这种连接,其效果是在不影响的情况下终止它。
换句话说,因为 RFC 793 明确表示在 RST
接收时不会发送任何响应,您必须进入 CLOSED
状态(某些与连接相关的情况除外在这种情况下你再次进入 LISTEN
状态)。
当您 close(2)
与接收数据挂起的连接时,连接断开,因为您没有读取所有挂起的数据(可以在缓冲区中、已确认、未确认或只是在传输中)你正在破坏状态机,这就是引发 RST
的原因(它从你的主机发送到另一端,响应到达连接这一端的任何数据段)。如果按照建议,您阅读了 RFC 文档,则连接处于错误状态,并且将用 RST
帧回复它收到的每个数据包……它不再处于 TIME_WAIT
状态。
在读取 EOF
之前调用 close(2)
(当您已经从另一端接收到 FIN
时,对 0 字节的无阻塞读取)条件 是协议错误 ,因为接收方(您)正在丢失传输到您这边的剩余数据。你有一个系统调用 shutdown(2)
来表示你不写入更多数据的意图(半关闭你的发送端),并允许等待剩余的数据到来,它迫使你的一方发送 FIN
到另一端并将连接置于 FIN_WAIT1
状态(等待来自另一端的 FIN
and/or FIN&ACK
的 ACK
)
注意
TIME_WAIT
状态是保证任何in-transit
数据包有足够时间到达目的地并被正确处理的状态。由于两端未同步 的连接失败,因此等待任何数据包到达是没有意义的,因为它们无法正确处理。没有数据包响应 RST
并且连接通常进入 CLOSED
状态。
RFC-793 具体说:
第 3.4 节建立连接
[...]
Reset Processing
In all states except SYN-SENT, all reset (RST) segments are validated
by checking their SEQ-fields. A reset is valid if its sequence number
is in the window. In the SYN-SENT state (a RST received in response
to an initial SYN), the RST is acceptable if the ACK field
acknowledges the SYN.
The receiver of a RST first validates it, then changes state. If the
receiver was in the LISTEN state, it ignores it. If the receiver was
in SYN-RECEIVED state and had previously been in the LISTEN state,
then the receiver returns to the LISTEN state, otherwise the receiver
aborts the connection and goes to the CLOSED state. If the receiver
was in any other state, it aborts the connection and advises the user
and goes to the CLOSED state.
因此,如您所见...在任何情况下 RST
都没有 TIME_WAIT
状态。
我知道 TIME_WAIT
是为了防止一个连接的延迟段被误解为后续连接的一部分。在连接处于 TIME_WAIT 等待状态时到达的任何段都将被丢弃。
在我的实验中,当客户端发送 RST 数据包而不是 FIN 数据包时,我看不到 TIME_WAIT
。为什么?
服务器
while (1) {
int len = sizeof(struct sockaddr);
fd = accept(sfd, &remote, &len);
read(fd, buf, sizeof(buf));
strcpy(buf, "Hello Client");
write(fd, buf, strlen(buf));
close(fd);
}
客户端
res = connect(sfd, result->ai_addr, result->ai_addrlen);
strcpy(buf, "Hello Server!");
write(sfd, buf, strlen(buf));
close(sfd);
注意:客户端发送 RST 而不是 FIN,因为它在关闭套接字之前不读取服务器已经发送的缓冲数据。
因为它声明不存在这种连接,其效果是在不影响的情况下终止它。
换句话说,因为 RFC 793 明确表示在 RST
接收时不会发送任何响应,您必须进入 CLOSED
状态(某些与连接相关的情况除外在这种情况下你再次进入 LISTEN
状态)。
当您 close(2)
与接收数据挂起的连接时,连接断开,因为您没有读取所有挂起的数据(可以在缓冲区中、已确认、未确认或只是在传输中)你正在破坏状态机,这就是引发 RST
的原因(它从你的主机发送到另一端,响应到达连接这一端的任何数据段)。如果按照建议,您阅读了 RFC 文档,则连接处于错误状态,并且将用 RST
帧回复它收到的每个数据包……它不再处于 TIME_WAIT
状态。
在读取 EOF
之前调用 close(2)
(当您已经从另一端接收到 FIN
时,对 0 字节的无阻塞读取)条件 是协议错误 ,因为接收方(您)正在丢失传输到您这边的剩余数据。你有一个系统调用 shutdown(2)
来表示你不写入更多数据的意图(半关闭你的发送端),并允许等待剩余的数据到来,它迫使你的一方发送 FIN
到另一端并将连接置于 FIN_WAIT1
状态(等待来自另一端的 FIN
and/or FIN&ACK
的 ACK
)
注意
TIME_WAIT
状态是保证任何in-transit
数据包有足够时间到达目的地并被正确处理的状态。由于两端未同步 的连接失败,因此等待任何数据包到达是没有意义的,因为它们无法正确处理。没有数据包响应 RST
并且连接通常进入 CLOSED
状态。
RFC-793 具体说:
第 3.4 节建立连接
[...]
Reset Processing
In all states except SYN-SENT, all reset (RST) segments are validated
by checking their SEQ-fields. A reset is valid if its sequence number
is in the window. In the SYN-SENT state (a RST received in response
to an initial SYN), the RST is acceptable if the ACK field
acknowledges the SYN.
The receiver of a RST first validates it, then changes state. If the
receiver was in the LISTEN state, it ignores it. If the receiver was
in SYN-RECEIVED state and had previously been in the LISTEN state,
then the receiver returns to the LISTEN state, otherwise the receiver
aborts the connection and goes to the CLOSED state. If the receiver
was in any other state, it aborts the connection and advises the user
and goes to the CLOSED state.
因此,如您所见...在任何情况下 RST
都没有 TIME_WAIT
状态。