This article is reprinted from the WeChat public account "Golang Technology Sharing", the author is Jijiling Chopping Knife. Please contact the Golang Technology Sharing public account for reprinting this article. In the article "Go Network Programming and TCP Packet Capture Practice", we wrote the Go version of the TCP server and client code, and used the tcpdump tool to capture and analyze the packets. In this example, the client code initiated a request to close the TCP connection by calling the Conn.Close() method, which is the default way to close the connection. The default closing requires four handshake confirmation processes, which is a way of "negotiation", while TCP provides us with another "forced" closing mode. How to force shutdown? How to implement it in Go code? This is what this article discusses. Default offI believe every programmer knows the four-wave process of TCP disconnection, which is the most common part of the interview essay. When we call the default Conn.Close() method in Go code, it is a typical four-wave process. Take the client actively closing the connection as an example. After calling the Close function, it will send a FIN message to the server. If there is no data in the server's local socket receive buffer, the server's read will get an EOF error. The party initiating the closing will experience the state changes of FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSE. These states need to be updated with feedback from the party being closed. Force CloseThe default closing method, whether it is initiated by the client or the server, requires the other party's response to finally achieve the real closing of the connection. So is it possible to end the connection without caring whether the other party agrees when initiating the closing? The answer is yes. The TCP protocol provides us with a RST flag. When one party of the connection thinks that the connection is abnormal, it can send a RST packet and immediately close the connection without waiting for the ACK confirmation from the closed party. SetLinger() method In Go, we can do this through the net.TCPConn.SetLinger() method.
The function comments are very clear, but readers are required to have the concept of socket buffer.
When the application layer code performs read and write operations through the socket, it actually passes through a layer of socket buffer, which is divided into a send buffer and a receive buffer. Buffer information can be viewed by executing the netstat -nt command
Among them, Recv-Q represents the receive buffer, and Send-Q represents the send buffer. In the default closing mode, sec < 0, the operating system will process all the unprocessed data in the buffer and then close the connection. When sec > 0, the operating system will run in the default shutdown mode. However, if the data in the buffer has not been processed after the defined time sec, the unfinished traffic in the buffer may be discarded in some operating systems. When sec == 0, the operating system will directly discard the traffic data in the buffer, which is a forced shutdown. Sample code and packet capture analysisWe will learn the usage of SetLinger() through sample code and use it to analyze the difference between forced closing and forced closing. Server code Example of actively closing the connection with the server
The server code is divided into four parts according to logic Part 1: Port listening. We open a TCP connection listener on port 8000 via net.Listen("tcp", ":8000"). Part 2: Establish a connection. After successfully opening the listener, call the net.Listener.Accept() method to wait for the TCP connection. The Accept method will wait for the new connection to arrive in a blocking manner and return the connection as a net.Conn interface type. Part 3: Data transmission. When the connection is established successfully, we will start a new goroutine to handle the reading and writing on the c connection. The data processing logic of the server in this article is that the client writes all the content of the TCP connection, and the server will write back the same content intact. Part 4: Forced connection closing logic. Start a new goroutine, set the forced closing option through c.(*net.TCPConn).SetLinger(0), and close the connection after 10 seconds. Client code Example of passively closing the connection with the client
The client code is divided into three parts according to logic Part 1: Establishing a connection. We connect a TCP connection via net.Dial("tcp", "localhost:8000") to the same localhost:8000 address that the server is listening on. Part 2: Write data. When the connection is established successfully, write the data Hi, gopher? to the server through the c.Write() method. Part 3: Reading data. Unless an error occurs, the client loops through the c.Read() method (remember, it is blocking) to read the content on the TCP connection. Tcpdump packet capture results Tcpdump is a very useful data packet capture tool. Its command options have been briefly introduced in the article "Go Network Programming and TCP Packet Capture Practice", so I will not repeat them here.
After the server and client establish a connection, the data Hi, gopher? is read from the client. After 10 seconds, the server forcibly closes the TCP connection, and the server code blocked in c.Read returns an error: use of closed network connection.
After the client and server establish a connection, they send data to the server, and the server returns the same data "Hi, gopher?" After 10 seconds, the server forcibly closes the TCP connection, so the client code blocked in c.Read captures the error: connection reset by peer.
We focus on the content Flags [], where [S] represents the SYN packet, which is used to establish a connection; [P] represents the PSH packet, indicating data transmission; [R] represents the RST packet, which is used to reset the connection; and [.] represents the corresponding ACK packet. For example, [S.] represents SYN-ACK. After understanding the meaning of these flags, we can analyze the entire process of TCP communication forced to be closed by the server. We compare the communication process of the client normally closing with the article "Go Network Programming and TCP Packet Capture Practice" As you can see, after setting SetLinger(0), when the active closing party calls Close(), the system kernel will directly send a RST packet to the passive closing party. This process does not require a reply from the passive closing party, and the connection is closed. The active closing party will not have the status change of FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSE in the default closing mode. SummarizeIn this article, we introduce two methods of TCP: default closing and forced closing (in fact, there is also a compromise method: SetLinger(sec > 0)), both of which are derived from the TCP protocol design. In most scenarios, we should choose to use the default closing method, because this ensures data integrity (data in the socket buffer will not be lost). When closed in the default way, each connection will go through a series of connection state transitions, leaving it on the operating system for a period of time, especially when the server actively closes the connection (in most application scenarios, the client should actively initiate the closing operation), which consumes server resources. If there are a large number of or malicious connections in a short period of time, we may need to use forced closure, because using forced closure can immediately close these connections, free up resources, and ensure the availability and performance of the server. Of course, we can also choose a compromise approach and tolerate a period of cache data processing time before closing the operation. Here is a question for readers to think about. If we change SetLinger(0) to SetLinger(1) in the example in this article, what will the packet capture result be? Finally, have readers ever used the forced shutdown method in their projects? |
<<: Front-end: Uniapp encapsulation network request notes
>>: 80% of the network traffic returned by Internet applications comes from it?
It may take some time for 5G to become the most a...
Labs Guide Currently, most campus networks are ne...
The Internet of Things is an important part of fu...
VMISS is offering a 30% discount on all VPS hosts...
CloudCone sent an email at the beginning of the m...
On November 16, the Ministry of Industry and Info...
[51CTO.com original article] Xiao Wang is an ordi...
The three major US mobile operators AT&T, T-M...
[[389986]] At the recently concluded MWC Shanghai...
[Original article from 51CTO.com] At the recently...
AI technology and TOT technology Ultimately, this...
As 5G network construction accelerates, related a...
Recently, China's three major operators have ...
2018 will be the year of WAN transformation, as r...
Author: Wang Rui, unit: Hebei Mobile Labs Guide A...