2.7 TIME_WAIT State
Undoubtedly, one of the most misunderstood
aspects of TCP with regard to network programming is its TIME_WAIT
state. We can see in Figure 2.4 that the
end that performs the active close goes through this state. The
duration that this endpoint remains in this state is twice the
maximum segment lifetime (MSL),
sometimes called 2MSL.
Every implementation of TCP must choose a value
for the MSL. The recommended value in RFC 1122 [Braden 1989] is 2
minutes, although Berkeley-derived implementations have
traditionally used a value of 30 seconds instead. This means the
duration of the TIME_WAIT state is between 1 and 4 minutes. The MSL
is the maximum amount of time that any given IP datagram can live
in a network. We know this time is bounded because every datagram
contains an 8-bit hop limit (the IPv4 TTL field in Figure
A.1 and the IPv6 hop limit field in Figure A.2) with a
maximum value of 255. Although this is a hop limit and not a true
time limit, the assumption is made that a packet with the maximum
hop limit of 255 cannot exist in a network for more than MSL
seconds.
The way in which a packet gets "lost" in a
network is usually the result of routing anomalies. A router
crashes or a link between two routers goes down and it takes the
routing protocols seconds or minutes to stabilize and find an
alternate path. During that time period, routing loops can occur
(router A sends packets to router B, and B sends them back to A)
and packets can get caught in these loops. In the meantime,
assuming the lost packet is a TCP segment, the sending TCP times
out and retransmits the packet, and the retransmitted packet gets
to the final destination by some alternate path. But sometime later
(up to MSL seconds after the lost packet started on its journey),
the routing loop is corrected and the packet that was lost in the
loop is sent to the final destination. This original packet is
called a lost duplicate or a
wandering duplicate. TCP must
handle these duplicates.
There are two reasons for the TIME_WAIT
state:
-
To implement
TCP's full-duplex connection termination reliably
-
To allow old
duplicate segments to expire in the network
The first reason can be explained by looking at
Figure 2.5 and
assuming that the final ACK is lost. The server will resend its
final FIN, so the client must maintain state information, allowing
it to resend the final ACK. If it did not maintain this
information, it would respond with an RST (a different type of TCP
segment), which would be interpreted by the server as an error. If
TCP is performing all the work necessary to terminate both
directions of data flow cleanly for a connection (its full-duplex
close), then it must correctly handle the loss of any of these four
segments. This example also shows why the end that performs the
active close is the end that remains in the TIME_WAIT state:
because that end is the one that might have to retransmit the final
ACK.
To understand the second reason for the
TIME_WAIT state, assume we have a TCP connection between
12.106.32.254 port 1500 and 206.168.112.219 port 21. This
connection is closed and then sometime later, we establish another
connection between the same IP addresses and ports: 12.106.32.254
port 1500 and 206.168.112.219 port 21. This latter connection is
called an incarnation of the
previous connection since the IP addresses and ports are the same.
TCP must prevent old duplicates from a connection from reappearing
at some later time and being misinterpreted as belonging to a new
incarnation of the same connection. To do this, TCP will not
initiate a new incarnation of a connection that is currently in the
TIME_WAIT state. Since the duration of the TIME_WAIT state is twice
the MSL, this allows MSL seconds for a packet in one direction to
be lost, and another MSL seconds for the reply to be lost. By
enforcing this rule, we are guaranteed that when we successfully
establish a TCP connection, all old duplicates from previous
incarnations of the connection have expired in the network.
There is an exception to this rule.
Berkeley-derived implementations will initiate a new incarnation of
a connection that is currently in the TIME_WAIT state if the
arriving SYN has a sequence number that is "greater than" the
ending sequence number from the previous incarnation. Pages 958鈥?59
of TCPv2 talk about this in more detail. This requires the server
to perform the active close, since the TIME_WAIT state must exist
on the end that receives the next SYN. This capability is used by
the rsh command. RFC 1185 [Jacobson, Braden, and Zhang
1990] talks about some pitfalls in doing this.
|