foreword
After a long time, you started to learn computer network, not for interviews, but to solve problems encountered in work. Before encountering network problems at work, your idea is that as a CRUD boy at work, the network is smooth. Don't worry about the network problem, but the network problem you encountered this time gave you a headache. You tried your best to solve this problem, and finally the problem was solved. After this problem is solved, you plan to study computer network thoroughly. Let’s talk about the three-way handshake. When I was preparing for the interview questions in the internship, the three-way handshake and the four-way handshake were high-frequency interview questions. I chose to give up this classic interview question because the computer network I learned in college was not good. , In fact, I was quite interested in the beginning, but later found that the more I listened, the more I couldn't understand it, so I simply started to brush Zhihu and read mathematics books. There is not much code, and the program is a bridge to recognize the computer world. Then the teacher obviously didn't realize this, and of course the school didn't realize it. In fact, there are other courses that also face such problems. But sometimes I will encounter it at work, so I have to spend time re-studying it, but I don't regret dedicating my time to mathematics in college. I miss that time, and suddenly I understand a certain mathematical theorem. I remember that it took a month or so How long did it take to solve an after-school problem in advanced algebra, and I was happy for a long time.
Let's recall the content of "TCP Study Notes (2) First Encounter":
TCP is a connection-oriented transport layer protocol, which means that an application must establish a TCP connection before using the TCP protocol, and after the data is released, the established TCP connection must be released.
TCP provides reliable delivery of services. Data sent over a TCP connection. No errors, no losses, no duplicates, and arrives in order.
In order to ensure no loss, after the packet is lost in the network environment, TCP establishes a retransmission mechanism. In the case of network congestion, the frequency of packet loss is relatively high. In this case, retransmission will further deepen the network congestion. degree, so TCP introduces congestion control.
TCP provides full duplex communication. TCP allows applications on both sides of the communication to send data at any time
TCP is a connection-oriented protocol, and a connection can be understood as a road between two communicating parties, through which messages are transported. There are three stages in the transmission of packets in TCP:
- connection establishment
- data transmission
- connection release
The establishment of a TCP connection is mainly to solve the following three problems:
- To enable both parties to communicate with each other to be sure of the existence of the other party
- To allow both parties to negotiate some parameters
- Ability to allocate transport entity resources (cache size, items in join table).
The establishment of the TCP connection adopts the client and server mode. The application process that actively initiates the connection establishment is called the client, and the application process that passively waits for the connection establishment is called the server. When I was writing TCP, I wanted to find a code example for the communication between two clients, because the TCP protocol used in Java generally has two classes, ServerSocket and Socket. ServerSocket is the server, and Socket is the client. Seeing this, I found that TCP itself is a client and server mode.
In this article, we mainly talk about connection establishment and connection release, that is, the three-way handshake and four-way handshake that are familiar to most programmers.
Connection establishment - three-packet handshake
In fact, it is a three-packet handshake, not a three-way handshake. In fact, three packets are exchanged in one handshake, not three times. I haven't found it for a long time, and I found it by searching for RFC 793. I wonder if the author made a mistake.) The corresponding description of the three-way handshake in RFC 793 is as follows:
The procedures to establish connections utilize the synchronize (SYN) control flag and involves an exchange of three messages. This exchange has been termed a three-way hand shake [3]
The program uses the SYN control flag to establish a connection and performs three message exchanges. This exchange is also called a three-message handshake.
The reason why the textbook thinks that it should be called a three-packet handshake is that the three-way handshake is literally inferred as three handshakes, but in fact, three packets are exchanged in one handshake, like shaking hands up and down three times at the first meeting.
I agree with this point of view. In the early days, when I saw the three-way handshake, I thought it was three handshakes. Let’s first briefly introduce the three-packet handshake to understand why. After exchanging three packets, the client and the server can confirm the existence of each other. and negotiate issues related to subsequent packet transmission.
The process of establishing a TCP connection is called a handshake. The handshake needs to exchange three TCP segments between the client and the server. In order to discuss the problem, we will now first introduce two communicating computers A and B. The communication process of A and B uses TCP protocol, A is the client, B is the server. At the beginning, the server process of B first creates a transport control block (TCB), and then the server process starts to process the Listen state and waits for the client's connection request. Writing here, have Java programmers thought of Socket programming in Java? In BIO, new ServerSocket is also used, and then a certain port is monitored, and then the accept method is called to listen to the client process. This method will block until a client request comes in. , will return a Socket object:
public void serverSocketDemo() throws Exception{
// 声明该Socket占用的进程
ServerSocket serverSocket = new ServerSocket(8080);
// 监听哪个端口
serverSocket.bind(new InetSocketAddress(9090));
// 开始监听,有客户端请求进来,会返回给一个Socket对象
// Socket中有输入输出流
// 可以用来读写数据
Socket socket = serverSocket.accept();
InputStream inputStream = socket.getInputStream();
OutputStream outPutStream = socket.getOutputStream();
}
Basically, the high-level language Socket programming is this step. First, the ServerSocket is created, and then the port is occupied. However, some of the listening methods are called accept, and some are called listen. In fact, they are all the same principle.
A's TCP process is also the first to create the transmission control module TCP. Then, when intending to establish a TCP connection, a connection request segment is sent to B, which is the same part in the header SYN=1, and an initial sequence number seq = x is selected at the same time. TCP stipulates that the SYN segment (ie the segment with SYN = 1) cannot carry any data, but consumes a sequence number. At this time, the TCP client process enters the SYN-SENT (synchronized sent state).
After receiving the connection request segment, B sends an acknowledgement to A if it agrees to establish the connection. In the confirmation segment, both the SYN bit and the ACK position should be set to 1, and the confirmation is ack = x + 1, and an initial sequence number seq=y will also be selected for itself. Note that this segment also cannot carry data, but also consumes a sequence number. This is the TCP server process entering the SYN-RCVD (synchronized received) state.
After the TCP client process receives the confirmation from B, it also needs to give confirmation to B. The ACK of the confirmation segment is set to 1, the confirmation number ack = y + 1, and its own sequence number seq = x + 1. The TCP standard specifies that the segment of the ACK can carry data. But if no data is carried, the sequence number is not consumed. In this case, the sequence number of the next data segment is still seq = x + 1. At this time, the TCP connection has been established, and A enters the ESTABLISHED state.
The connection establishment process given above is called a three-packet handshake, and the establishment process is shown in the following figure:
So for this process, the first question is why the client sends a confirmation message to the server after receiving the confirmation message from the server. This answer is answered in RFC-793:
The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.
The reason for the three-message handshake is to prevent confusion caused by the old repeated connection initialization.
Let's explain the above sentence through a scenario. Suppose that the first request message sent by A stays in some network nodes for a long time. A thinks the message has been lost, so it sends another request to establish The connected message, if the old message arrives at B earlier than the new one in this case, if there are only two handshakes, then B will think that two connections have been established with A, but in the old connection, A does not It will send data to B again, so the resources of server B will be wasted in vain. If it is a three-packet handshake, after receiving the old packet, B returns a SYN+ACK packet to the client. After the client receives it, it can judge that this is a historical connection (sequence number expired or timed out) according to its own context, then the client will send a request to terminate the connection message to the server, indicating that the connection is aborted this time, which can be avoided. Server-side resources are wasted.
In the case of network congestion, if only two packets are exchanged to establish a TCP connection, under network congestion, the client will send many packets requesting the establishment of a connection, and the server will receive a packet requesting the establishment of a connection. Just establishing a connection will cause a lot of waste of server resources.
TCP provides reliable transmission, and the sent and sent messages also need to be delivered in order. At the beginning of the connection establishment, the client's message has a serial number field, which is jointly maintained by both parties. The serial number is a key factor for reliable transmission. The role is:
- The receiver can deduplicate the data.
- The receiver can receive the packets in order according to the serial number of the packet
- It can identify which of the data packets sent out are received by the other party.
In fact, the acknowledgment message sent by B to A can also be split into two transmissions. You can first send an acknowledgment message end (ACK = 1, ack = x +1), and then send a synchronization message end (SYN = 1 , seq = y), this process becomes a four-message handshake, which can also achieve the same effect, but the mainstream implementation is to combine these two steps into one step.
Connection Release - Four Packet Waving
In fact, according to my initial thought, it is reasonable that the connection establishment needs to go through three packet handshakes, but to release the connection to go through four packet waves, I don't understand it. Can you just hang up at one time? You can think of such a scene in life, when two people call, one party hangs up before speaking, and usually hangs up too early and calls the other party again. Let's first introduce the process of connection release, and then ask questions.
First of all, the above two computers that have established connections, or two computer processes, and then A needs to close the connection at this time. A's application process first sends a connection release segment to its TCP, and stops sending data. Actively close the TCP connection. A sets the termination bit FIN of the connection release segment header to 1, and its sequence number seq = u, which is equal to the sequence number of the last byte of the previously transmitted data plus 1. At this time, A enters FIN-WAIT-1 (termination waiting 1) Status, waiting for B's confirmation. Note that TCP specifies that the FIN segment consumes a sequence number even if it does not carry data.
After B receives the connection release request, it sends an acknowledgment, and the confirmation is ack = u + 1, and the sequence number of this segment is v, which is equal to the sequence number of the last byte of the data that has been transmitted before B + 1. Then B will Enter the CLOSE-WAIT state (waiting for the closing state), but the TCP connection at this time encounters the semi-closed state for the first time, that is, A has no data to send, but if B wants to send data, A still has to receive, which is B to The connection in the direction of A has not been closed, and it may continue for a period of time.
After receiving the confirmation from B, A enters the FIN-WAIT-2 (termination waiting 2) state, waiting for the connection release segment sent by B. If B has no more data to send to A, its application process requests the operating system to release the connection through the TCP interface exposed by the operating system. At this time, the connection release segment sent by B must make FIN = 1. Now assume that the sequence number of B is w (in the half-closed state B may send some more data). B must also repeat the confirmation that it has sent last time, ack = u + 1. At this time, B enters the LAST-ACK (last confirmation) state and waits for A's confirmation.
After A receives B's connection release segment, it must confirm it. In the confirmation segment, set the ACK to 1, the confirmation number ack = w + 1, and its own sequence number is seq = u + 1 (according to the TCP standard, the previously sent FIN segment consumes a sequence number). Then enter the state of TIME-WAIT (time waiting). Note that the TCP connection has not been released yet. A must enter the CLOSED state after the time 2MSL set by the TIME-WAIT timer has elapsed. The time MSL is called the Maximum Segment Lifetime (Maxumum Segment Lifetime), RFC-793 (it seems that the textbook is indeed wrong, it is RFC-793 written here, and RFC-973 is the first introduction to TCP theory), RFC- 793 is recommended to be set to two minutes. This is purely an engineering consideration, MSL = 2 minutes may be a bit too long for today's networks. Therefore TCP allows different implementations to use smaller MSL values depending on the situation. Therefore, A enters the TIME-WAIT state, and it takes 4 minutes to enter the CLOSED state. When A withdraws the corresponding transmission control block TCB, this TCP connection ends.
The first question we ask is why does it take four times to recycle? In fact, the above waving process has already given the answer:
- When the connection is closed, when the client sends FIN to the server, it only means that the client no longer sends data, but can still receive data.
- When the server receives the FIN message from the client, it first returns an ACK response message, and the server may still have data to process and send. When the server no longer sends data, it sends a FIN message to the client to indicate unity. Now close the connection.
As can be seen from the above process, the server usually needs to wait for the completion of data transmission and processing, so the ACK and FIN of the server are generally sent separately, which is one more time than the three-way handshake. Let's draw a diagram to describe the process of waving four times:
As can be seen from the above process, the server usually needs to wait for the completion of data transmission and processing, so the ACK and FIN of the server are generally sent separately, which results in three more times than the three-way handshake.
The next question is why A needs to wait for 2MSL after sending the last connection release message.
- In order to ensure that the last ACK segment sent by A can reach B. This ACK message may be lost, so that B in the LAST-ACK state cannot receive the sent confirmation, and A can retransmit the confirmation during this time and restart the 2MSL timer. Finally, both A and B can enter the shutdown state normally.
- Prevent packets from old connections from being received. Assuming that the client has no TIME-WAIT time or the waiting time is too short, what happens to the delayed packet arrival?
If the TCP connection of the same port is multiplexed at this time, it is possible to receive the expired message normally, which will cause serious problems such as data confusion. During the waiting period, the 2MSL time is enough for the data packets in both directions to be discarded, so that the data packets of the original connection disappear naturally in the network, and the data packets that appear again must be established by the new connection.
TIME_WAIT waits for 2 times the MSL. A more reasonable explanation is: there may be packets from the sender in the network. When these packets from the sender are processed by the receiver, they will send a response to the other party, so it is necessary to go back and forth. Wait 2 times as long.
For example, if the passive closing party does not receive the last ACK message of the disconnection, it will trigger a timeout to resend the Fin message. After the other party receives the FIN, it will resend the ACK to the passive closing party. Back to exactly 2 MSL.
In fact, the question here is how TCP guarantees the longest segment lifetime. I thought that there would be such a field in the TCP message to describe its own lifetime. After consulting a lot of information, I found that I could not find the corresponding information. There are also people in StackOverFlow who have the same question as me. Search: What is Maximum Segment Lifetime(MSL) IN TCP related questions, you can see that the answerer has the same question as me.
So if the client restarts for no reason, will the connection to the server be closed? Of course not TCP also has a keep-alive timer. The server resets the keep-alive timer if it does not receive the client's data once, and the time setting is usually two hours. If the client's data is not received within two hours, the server sends a probe segment, and then sends it every 75 seconds. If there is still no response from the client after sending 10 probe segments in a row, the server considers the client to be faulty and then closes the connection.
TCP connections in time-wait cannot be reused. Generally, some people may ask when they see this. I use multiple threads to use HTTP Client multi-threaded calls. When the interval between the two is very short, it is also reused. That's because the operating system provides the option to reuse the port. Even if the port is still occupied by the previous connection and has not been released, we can still initiate a new connection by reusing the address:
public void serverSocketDemo() throws Exception{
Socket socket = new Socket();
// 允许处于time-wait中的端口,发起新的连接。
socket.setReuseAddress(true);
}
in conclusion
The three-way handshake we often talk about is more aptly called the three-packet handshake. Using SYN-related packets, the client and the server exchange three times. Why does the client need to send another confirmation after receiving the confirmation from the server? The reason is to prevent the old connection from causing connection confusion and waste of resources. If A sends a request to establish a connection message, the message stays in the network for a long time, exceeding the timeout, and A sends a request to establish a connection again. If there are only two handshakes, the lingering packets will also establish a connection, resulting in a waste of resources.
Then why does it take four times to close the connection, because after the client sends the data, the server may still have data that has not been processed and sent, so there is one more handshake. Then why does the client not close the connection immediately after receiving the connection close message sent by the server, but enter the TIMEWAIT state, there are two reasons, the first ensures that the connection is closed correctly, because the confirmation ACK message sent by A may Stuck and lost in the network, if A closes immediately after sending the acknowledgment message ACK, assuming the loss, the server may not be able to close the connection correctly. The second is to prevent old packets from being received by new connections. Consider the following two cases:
- If the network is extremely poor and B never receives the ACK sent by A, B will continue to retransmit until the retransmission time or number of times of the operating system is reached, and then close the connection; if A never receives the FIN retransmitted by B, it will retransmit the Release resources after waiting for 2 MSLs. Finally, A and B also complete the disconnection of the connection and the release of resources.
- The TIME_WAIT state waits for 2MSL, considering that B can always receive A's ACK, but due to congestion, it may be received slowly, the slowest is 1 MSL, if B still does not receive it after 1MSL, it will never be received. ACK, this time degenerates to the first case. At this time, 1MSL has passed since A sent the ACK, and B may have retransmitted the FIN many times, and because the ACK is received, the FIN will not be retransmitted later. At this time, if A has received a new FIN, it has already started to re-time and waits for 2 MSLs again; if A has not received a new FIN, it will wait for 1 MSL, so that B's previously retransmitted messages are on the network. disappeared in.
References
- Standard document for RFC 793 TCP https://www.rfc-editor.org/rfc/rfc793.txt
- "Computer Network (7th Edition)" by Xie Xiren, Electronic Industry Press
- What answers do interviewers want to hear about three handshakes and four waves? https://www.zhihu.com/question/271701044/answer/398114686
- Time-wait status (2MSL) some understanding https://blog.csdn.net/overstack/article/details/8833894
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。