4

I know that TIME_WAIT 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 TIME_WAIT when a client sends an RST packet instead of a FIN packet. Why?

Server

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

Client

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

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

close(sfd);

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

user207421
  • 305,947
  • 44
  • 307
  • 483
Pengcheng
  • 439
  • 1
  • 4
  • 14

2 Answers2

2

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)

NOTE

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.

Community
  • 1
  • 1
Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
  • 1
    why `RST` needn't `TIME_WAIT` state ? `RST` packet can also be delayed in the network. So, I think `TIME_WAIT` is nessary. – Pengcheng Jul 28 '16 at 04:46
  • @Pengcheng Your question asks why arrival of RST doesn't put a port into TIME_WAIT state. Your comment here refers to an RST packet that is itself delayed, i.e. that arrives *during* the TIME_WAIT state. It is a completely different condition and a completely different question. An RST that arrives during TIME_WAIT will abort it. . – user207421 Jul 29 '16 at 05:41
  • `RST` packet can be delayed, even lost in the network. Nobody waits for a `RST` packet. There's no sense to wait for a `RST` packet. `RST` packets are sent to the other side to inform of the unsynchronized state between two parties. You don't have to wait for them. – Luis Colorado Jul 29 '16 at 05:43
  • Even more... if **both implementations are correct**, the only way to provoque a `RST` is the one mentioned above (full closing a connection when data is in transit to here ---and it's an implementation dependency as it is not protocol related) or somebody injecting *in order* packets to force unsynchronized states at both ends. Even in that case, `TIME_WAIT` is not there to cope with `RST` packets. – Luis Colorado Jul 29 '16 at 05:48
  • @EJP If RST does not need **TIME_WAIT**, data error may happen in a fast speed network due to delayed **RST** packet. So, I think when server receives a **RST** packet, it should turn to **TIME_WAIT**. – Pengcheng Jul 29 '16 at 12:00
  • @Pengcheng, nope.... when you receive a `RST` packet you don't receive any other `RST`packet from the other end... you can loose it, but not receive it delayed.... You only receive one... and if you swith to `TIME_WAIT` due of a `RST` you'll not receive more `RST` packets (nor `FIN`, nor `ACK` with a sequence number past the one received in the connection) More, if you have received a `RST` because the injection of a data segment from a third party, you'll have acknowledge the incorrect data (the injected one) to the other end and given it for valid. – Luis Colorado Jul 29 '16 at 12:12
  • @Luis Colorado, I remember you said 'RST packet can be delayed'. Why not received it delayed? Why only receive one ? – Pengcheng Jul 29 '16 at 12:18
  • You can receive it delayed... but you are only going to receive one... so how can you detect at receiver it is delayed? you cannot. `RST` is only an indication of that the other end is abandoning the connection (it goes to the closed state) If you insist in sending more data, you'll receive (as part of the `LISTEN` part of the protocol) another `RST`, and so until you actually understand the connection has been broken and no chance of repairing it. – Luis Colorado Aug 01 '16 at 08:07
  • We can be debating during decades on this. But TCP is alive for almost 35 years and nobody has said `RST` needs to switch to `TIME_WAIT` state (there's no connection state, as both ends are unsynchronized, so I think the `CLOSED` state is the proper one to go to) If you don't agree, write IETF for an amendment in RFC-793 and not try to convince me of something that is not only useless, but incorrect. – Luis Colorado Aug 01 '16 at 08:09
0

Because it is stating that there is no such connection and its effect is to terminate it without prejudice.

To put it another way, because RFC 793 explicitly says that on RST reception no response is to be sent and you must go into the CLOSED state (except in some cases related to connection establishment in which case you go to the LISTEN state again).

Luis Colorado
  • 10,974
  • 1
  • 16
  • 31
user207421
  • 305,947
  • 44
  • 307
  • 483
  • By the way, the `RST` is **indeed part of the connection**, it has to comply with the serial sequence number of the point of break in the connection, and the acknowledge received up to this moment. If it doesn't fail in the window, it must be ignored, as fake. Indeed the reason to use cryptographically secure initial sequence numbers is to avoid DOS attacks consisting in using predictable sequence numbers to send RST segments and break connections. – Luis Colorado Jul 27 '16 at 19:58