Pengcheng Pengcheng - 2 months ago 5
Linux Question

Why does the RST packet not need the TIME_WAIT state?

I know that

is to prevent delayed segments from one connection being misinterpreted as being part of a subsequent connection. Any segments that arrive whilst a connection is in the TIME_WAIT wait state are discarded.

In my experiment, I can't see
when a client sends an RST packet instead of a FIN packet. Why?


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



res = connect(sfd, result->ai_addr, result->ai_addrlen);

strcpy(buf, "Hello Server!");
write(sfd, buf, strlen(buf));


NOTE: The client sends RST instead of FIN because it does not read buffered data already sent by the server before closing the socket.


When you close(2) a connection with pending of receiving data, the connection is broken, as you are not reading all the pending data (that can be in the buffer, acknowledged, unacknowledged or simply in transit) you are breaking the state machine and this is what provokes a RST (which is sent from your host to the other end, on response to any data segment that arrives to this side of the connection). If, as suggested, you read the RFC document, the connection is in an error state and will reply with a RST frame to every packet it receives... it is not anymore in the TIME_WAIT state.

Calling close(2) before reading the EOF (an unblocking read of 0 bytes, when you have already received a FIN from the other end) condition is a protocol error, as the receiving side (you) is lossing the remaining data in transit to your side. You have a system call shutdown(2) for the purpose of signalling your intention of not writing more data (half closing your sending side), and allow to wait for the remaining data to come, and it forces your side to send a FIN to the other end and put the connection in the FIN_WAIT1 state (waiting for the ACK of your FIN and/or FIN&ACK from the other side)


TIME_WAIT state is a state to ensure that any in-transit packet has enough time to arrive at destination and be correctly processed. As the connection has failed with both ends unsynchronized, there's no sense on waiting for any packet to arrive, as they cannot be correctly processed. No packet is sent in response to a RST and connection normally goes to the CLOSED state.

RFC-793 specifically says:

Sec 3.4 Establishing a connection


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.

So, as you can read... no TIME_WAIT state for RST in any case.