Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Example Analysis of the problem of socket connection closing

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly shows you the "example analysis of socket connection closure problem". The content is simple and easy to understand, and the organization is clear. I hope it can help you solve your doubts. Let Xiaobian lead you to study and learn the article "example analysis of socket connection closure problem".

Socket programming process often encounter such problems, there are these problems, some due to concurrent access caused by too much, some are due to programming in the code caused by carelessness. For example, one of the most common errors is that the program reports too many open files. When the socket established the connection, it was a three-way handshake, which everyone knew very well, but when the socket closed the connection, it needed to wave four times, but many people were not clear about the specific process of these four waves and suffered a lot.

CLOSE_WAIT analysis

Socket is a full-duplex communication method. After the socket connection is established, any party to the connection can initiate a shutdown operation. Let's assume that the closure of the connection is client-initiated. The client code is as follows:

Code snippet 1.1ret = CS_GetConnect(&client,ipAddr,9010);if (ret == 0) { printf("connected success. ");}CloseSocket(client);

The basic logic is that the connection is closed as soon as it is established. CloseSocket function is a custom function, which only encapsulates the different implementations of closing socket under windows and linux.

Code snippet 1.2#if defined(WIN32)|| defined(WIN64)#define CloseSocket(fd) do{ closesocket(fd);/* shutdown(fd, 2);*/ }while(0)#else#define CloseSocket(fd) do{ close(fd); /*shutdown(fd,2);*/ }while(0)#endif

After calling CloseSocket, the client sends a FIN signal to the server, telling the socket program that the connection has been disconnected. After receiving the FIN signal, the server will set its TCP status to `CLOSE_WAIT` and reply an ACK signal to the client. After receiving the ACK signal, the client will be in `FIN_WAIT_2` status.

But tcp is a full-duplex communication protocol. Although the client closes the connection, what if the server ignores this shutdown action? This is unfortunate news for the server, because it will always be in the state of CLOSE_WAIT, although the client no longer needs to communicate with the server, but the socket connection handle on the server side has not been released; if this situation persists, the connection handle on the server side will be exhausted over time. For the client initiating shutdown, it is in `FIN_WAIT_2` state. If the server is always in `CLOSE_WATI` state, the client will not always be in `FIN_WAIT_2` state because there is a timeout period for this state. This value can be configured in/etc/sysctl.conf. Configure `net.ipv4.tcp_fin_timeout=30` in this file to ensure that `FIN_WAIT_2` stays in the state for 30 seconds at most. After this time, it enters the TIME_WAIT state (we will talk about this state below).

Note: The socket closure is initiated from the client side, just for example, the socket closure can also be initiated from the server side. For example, if you write a crawler program to download resources on some web servers on the Internet, some web resources to be downloaded do not exist, the web server will immediately close the current socket connection, but your crawler program is not robust enough to handle this situation, which will also make your crawler client in CLOSE_WAIT state.

So how to prevent SOCKET from being in CLOSE_WATI state? The answer is here:

Code snippet 1.3 while(true) { memset(getBuffer,0,MY_SOCKET_BUFFER_SIZE); Ret = recv(client, getBuffer, MY_SOCKET_BUFFER_SIZE, 0); if ( Ret == 0 || Ret == SOCKET_ERROR ) { printf("The other socket has exited,Ret [ %d]!\ n",Ret); Ret = SOCKET_READE_ERROR;//Failed to receive server-side information break; } }clear: if (getBuffer != NULL) { free(getBuffer); getBuffer = NULL; } closesocket(client);

Here is an excerpt from the server-side code. Note the recv function. This function will block the current code when the connection is established. It will return only after the data is successfully received. The return value is the number of bytes received. However, for the connection to the other socket closed, it can immediately sense, and return 0. So for the return of 0, you can jump out of the loop, end the current socket processing, do some garbage collection work, note that the last sentence closesocket operation is very important, assuming that this sentence is not written, the server will always be in CLOSE_WAIT state. If you write this sentence, then the socket flow will be like this:

TIME_WAIT Analysis

After the CloseSocket operation is invoked, the server sends a FIN signal to the client, and the client enters the `TIME_WAIT` state, and will remain in this state for a period of time, which is also called 2MSL.(MSL is the abbreviation of maximum segment lifetime, meaning the maximum segment lifetime, which is the longest time IP packets can survive on the Internet, beyond which they will disappear on the Internet). If the data sent by the client has not been confirmed by the server during this time period, you can wait for the confirmation message from the server. Note that the last ACK N+1 message sent by the client is sent as soon as the `TIME_WAIT` state is entered, not after the `TIME_WAIT` state ends. If the ACK N+1 is not received by the server for some reason, the server will resend the FIN N message. At this time, if the client is still in the `TIME_WAIT` state, the ACK N+1 message will be resend. Otherwise, the client will directly send a RST message to tell the server that the socket connection no longer exists.

Sometimes, when we check the tcp status on the web server side using the netstat command, we find that there are thousands of connection handles in the `TIME_WAIT` state. The socket connection of the web server is generally closed by the server side actively. When the concurrent access volume of the web server is too large, because the web server is mostly a short connection, the life cycle of the socket handle is relatively short, so a large number of handles are blocked in the `TIME_WAIT` state, waiting for the system to recover. If this happens too frequently, and because the operating system itself has a limited number of connections, it will definitely affect the establishment of normal socket connections. In linux, there is a remedy for this situation, by modifying the/etc/sysctl.conf file to ensure that it contains the following three lines of configuration:

Configuration Type 2.1

#means reuse is enabled. Allow TIME-WAIT sockets to be reused for new TCP connections, default is 0, means closed

net.ipv4.tcp_tw_reuse = 1

#means to enable the quick recovery of TIME-WAIT sockets in TCP connections, default is 0, means to close

net.ipv4.tcp_tw_recycle = 1

#indicates the maximum number of TIME_WAITs the system can hold simultaneously. If this number is exceeded,

#TIME_WAIT will be cleared immediately and a warning message printed. Default is 180000, changed to 5000.

net.ipv4.tcp_max_tw_buckets = 5000

The operation of reusing the handle of the TIME_WAIT state can also be set in the code:

snippet 2.1int on = 1;if (setsockopt(socketfd/* sockethandle */,SOL_SOCKET,SO_REUSEADDR,(char *)&on,sizeof(on)){ return ERROR_SET_REUSE_ADDR;}

If an action on reuse is set in the code, the program will use the options set in the code to decide whether to reuse or not, and the settings in `net.ipv4.tcp_tw_reuse` in/etc/sysctl.conf will no longer have effect.

Of course, this setting is contrary to TCP design standards, because TCP connections in the `TIME_WAIT` state have positive effects, as described above. Suppose the client fails to send ACK N+1, and the server resends FIN N after 1MSL. At this time, the client reuses the previously closed connection handle to establish a new connection, but at this time it receives a FIN signal, causing it to be inexplicably closed.

TIME_WAIT is usually maintained at 2MSL (the default is 30 seconds for 1MSL under Linux), but this time can be modified by code:

generation chip segment 2.2 struct linger so_linger;so_linger.l_onoff = 1;so_linger.l_linger = 10;if (setsockopt(socketfd,SOL_SOCKET,SO_LINGER,(char *)&so_linger,sizeof(struct linger)){ return ERROR_SET_LINGER;}

Here the code sets the time for TIME_WAIT to 10 seconds (on BSD it would be 0.01*10s). The TIME_WAIT mechanism in TCP allows socket programs to close "gracefully." If you want your program to be more elegant, it's best not to set the TIME_WAIT dwell time and let old tcp packets die in a reasonable amount of time. Of course, for the SO_LINGER parameter, it can not only customize the time of the TIME_WAIT state, but also disable the TCP four waves directly. Suppose the setting of the so_linger structure variable is like this:

so_linger.l_onoff = 1;

so_linger.l_linger = 0;

If the client socket is set like this, then the socket closure process is directly like this:

This is equivalent to the client telling the server that I terminated abnormally and that you can discard all the packets I give you later. If the server receives this RST message, it will directly recycle the corresponding socket handle. Some socket programs do not want TCP to appear in the `TIME_WAIT` state, and will choose to close the socket directly using RST mode to ensure that the socket handle is recovered in the shortest time. Of course, the premise is to accept the possibility of dropping old packets. If the correlation between the packets before and after socket communication is not very strong, in other words, each communication is a separate transaction, then you can consider sending RST signal directly to quickly close the connection.

supplementary

1. The modification of the/etc/sysctl.conf file mentioned in this article takes effect only after running `/sbin/sysctl -p` after the modification is completed.

2. After sending the FIN M signal in Figure 1, the input stream in the socket program at the passive close end will receive an EOF indicator, which is that when the recv function returns 0 in C code, it means that the other party is closed. In java code, it will receive-1 in the read function of InputStream:

Socket client = new Socket();//, 9090 try { client.connect( new InetSocketAddress("192.168.56.101",9090)); while(true){ int c = client.getInputStream().read(); if (c > 0) { System.out.print((char) c); } else {//If the other socket is closed, the read function returns-1 break; } try { Thread.currentThread().sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } } } catch (IOException e2) { e2.printStackTrace(); } finally { try { client.close(); } catch (IOException e) { e.printStackTrace(); } }}

3. If the active shutdown party has initiated a shutdown FIN signal, the passive shutdown party ignores it and still sends data to the active shutdown party, then the active shutdown party will directly return RST new number, and the handles of both parties will be recovered by the operating systems of both parties. If there are still unarrived data before the routing nodes of both parties at this time, they will be discarded.

4. In the process of communication, if the process of one party in the socket double-send unexpectedly exits, this party will send RST messages to its corresponding other party, all the connections established by the double-send will be recycled, and the unfinished messages will be discarded.

The above is all the content of this article "socket connection closure problem example analysis", thank you for reading! I believe that everyone has a certain understanding, hope to share the content to help everyone, if you still want to learn more knowledge, welcome to pay attention to the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report