Regarding the establishment and termination of a TCP connection, the tcp connection is terminated.
0. Preface
Recently, when dealing with the company's legacy projects, I found that I didn't understand the TCP protocol at all, so I made up some content about the establishment and termination of the TCP connection. Here I will briefly write down what I know, the irrelevant fields of the message serial number validation sequence are omitted. This article mainly discusses TCP status conversion and some issues in Linux.
This article mainly records some of your problems and learned things.
For the TCP/IP protocol, we recommend a book: "TCP/IP protocol details: Volume 1".
1. Establish a TCP connection
All those who have learned about computer networks know that TCP connections require three handshakes. At that time, they listened in college, but they did not know this until they have been completed three times recently.
For the client/server model:
1. First, the client initiates a connection (send the SYN Packet and enter the SYN_SENT status)
2. The server receives the SYN and then responds (send the syn ack to enter the SYN_RCVD status. Note that the connection is not established at this time)
3. After the client receives the request, it sends a confirmation message (ACK is sent and enters the Established status)
4. After receiving the message, the server enters the state of link establishment (Established.
For example, the figure shown in Baidu)
2. Termination of TCP Connection
For the termination of TCP connection, it takes four waves to complete. Here, the customer/server model is used, and the client actively initiates the shutdown (the server can also initiate the shutdown ).
1. The client sends FIN (entering the FIN_WAIT_1 status)
2. The server receives the FIN and confirms the ACK (the server enters the CLOSE_WAIT status, and the client changes from FIN_WAIT_1 to FIN_WAIT_2 after receiving the ACK)
3. The server calls close to send FIN (entering the LASK_ACK status)
4. The client sends ACK after receiving the FIN sent by the server (entering the TIME_WAIT status)
5. After the server receives the message, it stops (the LASK_ACK status is changed to virtual CLOSED, that is, it is no longer in the status)
As shown in:
3. TCP status transition
In fact, if you understand the establishment and termination of the above connection, it is easy to understand the following state transition diagram, the above two can be seen as being disassembled by it.
4. CLOSE_WAIT status
As mentioned above, the Code for maintaining some historical projects is simply a log, directly using two processes to share a select statement and adding a file lock before accept, select only listens to the server fd, and other fd does not listen .... (One thousand words are omitted here), and now there are a lot of CLOSE_WAIT statuses. I wonder if I have never seen them before? Wonderful. However, some DDoS attacks may also cause this phenomenon. Finally, I discussed how to make minor changes to the original code one afternoon. At last, I decided to rewrite the select part ~ ^ ~, Use epoll.
The preceding status chart shows that the server enters CLOSE_WAIT because it receives the FIN from the client. If the server does not listen to the fd of the client and does not call close, in this case, the occupied FD is not released, and the resource is leaked. This will also lead to a large number of CLOSE_WAIT statuses, so that when the FD is used up (the default value is 1024), accept will fail. (Note: here the CLOSE_WAIT status is caused by the application not calling close, and the system will not release the resource, that is, it will always exist)
(Note: even if the accept fails, the link can still be established successfully, because for the underlying implementation of Linux TCP, there are two queues, one is a half-link queue, another queue is a link that is successfully handshakes three times but not removed by the Server accept .)
In the future, epoll is generally used for Linux servers, which is more efficient than select.
5. Supplement
Here we can see some blogs that set system parameters to change the CLOSE_WAIT maintenance wait time. I checked it and tried it (in fact, I don't need to try it ). It cannot be changed by setting system parameters, because the application is caused internally, and there is no such thing as CLOSE_WAIT maintenance time, this state is changed to another State (or closed) only when the application calls close. Here, by modifying system parameters, the maintenance time of the TIME_WAIT State is usually indicated.