Monday, November 4, 2013

TCP Connection States with an Example

Often I tend to get confused with the TCP states showing up in the output of netstat -an. I have gone through the theoretical explanation a number of times. One of the good references I came across is from Microsoft Support knowledge base article at-

http://support.microsoft.com/kb/137984

However, over time, i have learnt that unless you couple theory with hands on, it is very difficult to remember the things.

Following is an example of how the connection states changed when I installed Redis master and slave instances in my host and brought up and shutdown the slave instance.

Note that my redis master instance was configured to run on port 6379 while the slave was configured to run on 6389 (that is, clients could connect with redis instances on these ports).
  1. Initial netstat -an Output (before slave is brought up)$ netstat -an | grep 6379
    tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN
    • This indicates that my master redis instance is running on port 6379 and is is ready to accept connection (indicated by connection state LISTEN).
  2.  After Slave is Started$ netstat -an | grep 6379
    tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN     
    tcp        0      0 127.0.0.1:6379              127.0.0.1:53525             ESTABLISHED
    tcp        0      0 127.0.0.1:53525             127.0.0.1:6379              ESTABLISHED
    • This indicates that the server has established a connection with the slave (running on the same host) on port 53525 (indicated by connection state ESTABLISHED).
    •  Since, both master and slave are located on the same host, we also see another line (third one in the output) that says that the slave has established a connection with the master on the port 53525.
    • The first line in the output indicates that the master is ready to accept more connections.
  3.  After Slave is Shutdown$ netstat -an | grep 6379
    tcp        0      0 0.0.0.0:6379                0.0.0.0:*                   LISTEN     
    tcp        0      0 127.0.0.1:53525             127.0.0.1:6379              TIME_WAIT
    • The second line in the output indicates that the slave (client in our master-slave setup) is in the TIME_WAIT state. This means that the the server accepted the client initiated connection close request and closed the connection from its side too (it sends a FIN request to the client after sending the ACK for the client's FIN, and client too has sent an ACK for the server FIN).
    • As per RFC793, a connection could show up in TIME_WAIT state on client side for up to 4 minutes by default (twice the Maximum Segment Lifetime (MSL)).
  4.  Note that in between, the connection goes through various other states on both server and client sides. Some of the states are for client side while some or for the server side. Since my client-server were on the same host and it happened pretty fast, I cold not see those states in the netstat output.
  5.  A state generally indicating some error condition on server side is CLOSE_WAIT. CLOSE_WAIT Indicates passive close, that is, server just received first FIN from a client. If a connection continues to show as CLOSE_WAIT even long after the client has closed the connection from its side, it indicates that the client properly closed the connection (FIN has been sent), but the server still has its socket open. This could be the result of one instance (among all threads or processes) of the socket not being closed.
  6.  Server Side States-
    • LISTEN- Server is ready to accept connection
    • SYN_RECEIVED- Server just received SYN from the client
    • ESTABLISHED- Server has received ACK from client for its SYN
    • CLOSE_WAIT- Indicates passive close. Server just received first FIN from a client.
    •  LAST_ACK- Server is in this state when it sends its own FIN.
    •  CLOSED- Server received ACK from client and connection is closed.
  7. Client Side States-
    • SYN_SEND- Indicates active open.
    • ESTABLISHED- Client received server's SYN and session is established.
    • FIN_WAIT_1- Indicates active close (client just sent a FIN request to the server).
    • FIN_WAIT_2- Client just received acknowledgment of its first FIN from the server.
  8.  Wikipedia has a wondeful diagram explaining the connection establish and tear down handshake. I am reproducing it here.

No comments: