为什么RST数据包不需要TIME_WAIT状态?

时间:2016-07-26 02:00:49

标签: c linux sockets tcp 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,因为它在关闭套接字之前没有读取服务器已经发送的缓冲数据。

2 个答案:

答案 0 :(得分:2)

当您close(2)与挂起接收数据的连接时,连接断开,因为您没有读取所有待处理数据(可以在缓冲区中,已确认,未确认或仅在传输中)您是打破状态机,这就是激发RST(从主机发送到另一端,响应任何到达连接这一端的数据段)的原因。如果按照建议读取RFC文档,则连接处于错误状态,并且会向其收到的每个数据包回复RST帧...它不再处于TIME_WAIT状态。

在读取close(2)之前调用EOF(当您从另一端收到FIN时,取消阻止读取0字节)条件是协议错误< / strong>,因为接收方(您)正在丢失传输到您身边的剩余数据。你有一个系统调用shutdown(2),目的是表明你没有写更多数据的意图(一半关闭你的发送方),并允许等待剩余的数据来,它强迫你的一方发送一个{ {1}}到另一端并将连接置于FIN状态(等待FIN_WAIT1的{​​{1}}和/或来自另一方的ACK < / p>

FIN状态是一种状态,用于确保任何FIN&ACK数据包有足够的时间到达目的地并正确处理。由于连接失败,两端未同步,因此等待任何数据包到达没有任何意义,因为无法正确处理。没有数据包响应TIME_WAIT而发送,连接通常会进入in-transit状态。

RFC-793具体说:

Sec 3.4建立连接

[...]

RST

所以,你可以在任何情况下阅读...... CLOSED没有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. 州。

答案 1 :(得分:0)

因为它声明没有这种联系,其效果是在没有偏见的情况下终止它。

换句话说,因为RFC 793明确表示在RST接收时不会发送任何响应,您必须进入CLOSED状态(除了在某些情况下与连接建立有关)在哪种情况下你再次进入LISTEN状态。