Title: The Relationship Between Java Sockets and TCP/IP Protocol Stack, Why Does TCP Connection Require Three-way Handshake and Four-way Teardown?

This article takes about 17 minutes to read.
OSI Seven Layer Model and TCP/IP Four Layer Model
Many students know that in the university course, the book “Computer Networks” we studied adopts the OSI seven-layer network model (OSI Model). However, the OSI seven-layer model is an abstract model, and the TCP/IP four-layer network model is used in the actual implementation of the operating system. The four-layer model combines the seven layers into the application layer (Application Layer), transport layer (Transport Layer), internet layer (Internet Layer), and link layer (Link Layer), simplifying the network system in practical implementation. The relationship between the OSI seven-layer model and the TCP/IP four-layer model and their corresponding protocols is shown in the table below. In computer systems, layering is an important programming concept. The layering concept hierarchically divides the functions and responsibilities of the system, and basically all system architecture designs are designed according to the layered architecture as the basic structure. In computer networks, the same layer has the same protocol processing method, the lower layer protocol provides services to the upper layer, and the behavior of the upper layer protocol controls the working state of the lower layer. The responsibilities between layers are singular and the objectives are clear.

Two
Java’s Implementation of TCP/IP Protocol
In network program development, operating systems provide us with comprehensive and convenient application layer network operation classes and interfaces, allowing programmers to focus on data transmission processing without worrying about the details of the protocol stack. Of course, the operating system also provides programmers with the opportunity to control protocol details, for example, using raw sockets (Raw Socket) can control the details of TCP’s three-way handshake to implement TCP SYN scanning (note that some Windows 7 systems do not support raw socket half-open scanning). However, in most conventional network application development, we directly use the application layer interfaces provided by the system to implement network programs. Here, we list common TCP/IP protocol implementation classes or methods in Java, as shown in the table below:

Three
Why Does TCP Protocol Require Three-way Handshake?
First, let’s look at the specific process of TCP protocol’s three-way handshake (this image is sourced from the internet):

First Handshake: Establishing a connection. The client sends a connection request segment, setting SYN to 1 and Sequence Number to x; then the client enters the SYN_SEND state, waiting for the server’s confirmation;
Second Handshake: The server receives the SYN segment. The server, upon receiving the client’s SYN segment, needs to confirm this SYN segment by setting the Acknowledgment Number to x+1 (Sequence Number + 1); at the same time, it must also send a SYN request, setting SYN to 1 and Sequence Number to y; the server combines all this information into a segment (i.e., SYN+ACK segment) and sends it to the client, at which point the server enters the SYN_RECV state;
Third Handshake: The client receives the server’s SYN+ACK segment. It then sets the Acknowledgment Number to y+1 and sends an ACK segment to the server. After this segment is sent, both the client and server enter the ESTABLISHED state, completing the TCP three-way handshake.
So, why does the TCP protocol require a three-way handshake? In Xie Xiren’s “Computer Networks”, it is stated that:
Invalid connection request segments may occur in situations where the first connection request segment sent by the client is not lost, but is delayed at some network node for a long time, and arrives at the server after the connection has already been released. This is an already invalid segment. However, when the server receives this invalid connection request segment, it mistakenly believes it is a new connection request from the client. Therefore, it sends a confirmation segment to the client, agreeing to establish a connection. If we did not adopt the “three-way handshake”, then as soon as the server sends a confirmation, a new connection would be established. Since the client has not made a request to establish a connection, it would ignore the server’s confirmation and would not send data to the server. However, the server would think a new transport connection has been established and would wait for the client to send data. In this way, many of the server’s resources would be wasted. The “three-way handshake” method can prevent the above phenomenon from occurring. For example, in the aforementioned situation, the client would not send a confirmation to the server. The server, not receiving the confirmation, would know that the client has not requested to establish a connection.
In other words, the reason why TCP uses a three-way handshake mechanism to establish a connection is to prevent invalid connection request segments from suddenly being transmitted to the server, causing errors.In the network, it cannot be ensured that packets are sent successfully, nor can it be ensured that the sending order and arrival order of packets are consistent. The three-way handshake mechanism avoids the phenomenon where one end cannot perceive the state of the other end when establishing a connection due to packet loss. The four-way teardown process and reasons for the TCP protocol are identical to the three-way handshake, which will not be elaborated here. Regarding the closing of TCP connections, we will analyze a related issue: the TCP half-close phenomenon, and first, let’s look at how to establish a TCP connection using the Socket class in Java.
Four
Related Implementations of TCP Communication in Java
In the previous section, we analyzed the specific implementation methods of establishing a TCP connection, data transmission, and closing connections. In actual development, programmers only need to understand that TCP is a reliable transport protocol to achieve stable data transmission between clients and servers. In Java, the Socket and SocketServer classes are provided to implement related functions of TCP servers and clients. A normal TCP communication process can be roughly divided into four steps (BIO mode):
-
The server side (ServerSocket) binds to a listening port and waits for TCP connections from the client (
ServerSocket.accept()) -
The client (Socket) connects to the server’s listening port via IP address and port (
Socket.Connect()). Upon successful connection, the server returns a Socket object representing the TCP connection. -
The client and server transmit data by opening the InputStream and OutputStream data streams of the Socket object (Java provides stream operation interfaces for I/O-related operations, and network interface operations follow the same pattern).
-
The client and server complete data transmission, close the data streams, and close the TCP connection (
Socket.close()).
The following diagram illustrates the Socket model:

Here’s a question: At which step of the Socket is the TCP three-way handshake implemented?
It is implemented during ServerSocket.accept() and Socket.Connect(). When the client connects to the server through the Connect() interface, the underlying TCP/IP protocol stack of the operating system begins to send SYN packets, respond with SYN+1, and carry out the TCP three-way handshake process. Only when the three-way handshake is successful will ServerSocket.accept() return a valid Socket object, and the client’s Socket.Connect() function will return normally. If the three-way handshake fails, the client’s Socket.Connect() will throw an IOException exception.
It should be noted that the specific implementation details of the three-way handshake protocol are not implemented in Java; Java is just a language running on the JVM virtual machine, and the actual implementation is provided by the TCP/IP protocol stack of the host machine. Java merely calls the methods provided by the host machine through the virtual machine.
Five
TCP Half-Close Phenomenon (Half-Close)
Students with experience in developing TCP server and client applications should have encountered a problem where the server suddenly crashes (the server process is killed), and when checking the network connections in the system, the TCP client’s status is still in a connected state (ESTABLISHED), while this TCP connection has actually become invalid. This is the TCP Half-Close phenomenon. If the method for the application program to judge the connection status with the server relies on the TCP connection state, the client will always believe that the TCP connection with the server is normal, and only when the client attempts to send data to the server will it discover that the TCP connection corresponding to the socket has become invalid. The reason for the Half-Close phenomenon is that the TCP connection between the client and server has not been closed using the four-way teardown method, and the sudden offline of the server causes the client to be unable to perceive the problem immediately. Some students may ask, isn’t there a timeout? Once the timeout occurs, won’t the client be able to perceive that the server is offline? Yes, the protocol stack implementation of the system has a timeout mechanism; however, in Windows systems, this timeout is set to 2 hours by default (the author has not verified the keepAlive time under Linux).
So how can we avoid the Half-Close phenomenon?
1. First, after using the TCP connection, always ensure to close the socket.
2. Implement a heartbeat packet mechanism. The connection maintenance mechanism between the server and client should not rely on the socket state but should design a heartbeat packet mechanism above the TCP protocol. For example, every 5 minutes, the client and server can send heartbeat packets to perceive each other’s presence.
3. The TCP Server should implement the JVM’s shutdown hook (Runtime.addShutdownHook()) to actively close all TCP connections and clean up occupied resources. The usage of the JVM shutdown hook is as follows:

Summary
The TCP protocol, as a reliable transport protocol, is the most commonly used protocol among all protocols. What? Isn’t the most commonly used protocol HTTP? The HTTP protocol is merely an application protocol of the TCP protocol. The development challenges related to the TCP protocol lie mainly in the server-side development, where concurrent performance must be considered. This article primarily explains the TCP protocol, thus only the BIO mode is analyzed. In subsequent articles, we will analyze the implementation principles of high-concurrency TCP servers.
