Home TCP Connections - How Data Gets From Point A to Point B
Post
Cancel

TCP Connections - How Data Gets From Point A to Point B

Introduction

In simple terms, when two devices want to communicate with each other over the network using TCP, they first establish a connection. This connection is like a virtual pipeline between the two devices, through which they can send and receive data. Once the connection is established, the devices can send data packets to each other.

TCP ensures that the data packets are delivered in the correct order and without any errors. It also ensures that the packets are retransmitted if they are lost during transmission. This makes TCP a very reliable protocol for sending and receiving data over the network.

When the communication between the two devices is complete, they terminate the connection.

Overall, TCP is a protocol that ensures reliable communication between devices over the network, TCP ensures that all data packets are delivered and received correctly before the connection is closed.

Server Program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Server.java
import java.io.*;
import java.net.*;
import java.util.Scanner;

public class Server {
    public static void main(String[] args) throws IOException {
        int portNumber = 1234;

        // Create a new server socket on the specified port
        try (
            ServerSocket serverSocket =
                new ServerSocket(portNumber);
            // Wait for a client to connect and create a socket for communication
            Socket clientSocket = serverSocket.accept();
            // Create a writer object to send messages to the client
            PrintWriter out =
                new PrintWriter(clientSocket.getOutputStream(), true);
            // Create a reader object to receive messages from the client
            BufferedReader in = new BufferedReader(
                new InputStreamReader(clientSocket.getInputStream()));
            // Create a scanner object to read user input from the console
            Scanner scanner = new Scanner(System.in)
        ) {
            String inputLine;
            // Loop to receive messages from the client
            while ((inputLine = in.readLine()) != null) {
                // Print the client's message to the console
                System.out.println("Client: " + inputLine);
                // Prompt the server to enter a message
                System.out.print("Server: ");
                // Read a message from the console
                String serverMessage = scanner.nextLine();
                // Check if the message is the exit command, and break the loop if it is
                if (serverMessage.equals("exit")) {
                    break;
                }
                // Send the server's message to the client
                out.println(serverMessage);
            }
        } catch (IOException e) {
            // Handle any exceptions that may occur during the execution of the program
            System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
            System.out.println(e.getMessage());
        }
    }
}

Here’s an explanation of the Java code line by line:

1
2
3
import java.io.*;
import java.net.*;
import java.util.Scanner;

This imports the necessary Java packages for input and output, networking, and user input.

1
2
3
public class Server {
    public static void main(String[] args) throws IOException {
        int portNumber = 1234;

This declares the main class and method, and initializes a port number for the server to listen on.

1
2
3
4
5
6
7
try (
    ServerSocket serverSocket = new ServerSocket(portNumber);
    Socket clientSocket = serverSocket.accept();
    PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
    BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
    Scanner scanner = new Scanner(System.in)
) {

This begins a try block that creates a new ServerSocket object on the specified port number, waits for a client to connect and creates a Socket object for communication, creates a PrintWriter object to send messages to the client, creates a BufferedReader object to receive messages from the client, and creates a Scanner object to read user input from the console.

1
2
3
4
5
6
7
8
9
10
String inputLine;
while ((inputLine = in.readLine()) != null) {
    System.out.println("Client: " + inputLine);
    System.out.print("Server: ");
    String serverMessage = scanner.nextLine();
    if (serverMessage.equals("exit")) {
        break;
    }
    out.println(serverMessage);
}

This creates a String variable to hold the input from the client, and enters a loop to receive messages from the client. Inside the loop, the client’s message is printed to the console, the server prompts the user to enter a message, and the user enters a message from the console. If the user enters the “exit” command, the loop is broken. Otherwise, the server’s message is sent to the client using the PrintWriter object.

1
2
3
4
} catch (IOException e) {
    System.out.println("Exception caught when trying to listen on port " + portNumber + " or listening for a connection");
    System.out.println(e.getMessage());
}

This catches any exceptions that may occur during the execution of the program, and prints an error message to the console.

Overall, this Java code creates a simple server that listens on a specified port, waits for a client to connect, receives messages from the client, and sends messages back to the client. The server continues to receive and send messages until the user enters the “exit” command to terminate the connection.

Client Program

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Client.java
import java.io.*;
import java.net.*;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws IOException {
        String hostName = "localhost";
        int portNumber = 1234;

        try (
            // Connect to the server on the specified port
            Socket socket = new Socket(hostName, portNumber);
            // Create a writer object to send messages to the server
            PrintWriter out =
                new PrintWriter(socket.getOutputStream(), true);
            // Create a reader object to receive messages from the server
            BufferedReader in = new BufferedReader(
                new InputStreamReader(socket.getInputStream()));
            // Create a scanner object to read user input from the console
            Scanner scanner = new Scanner(System.in)
        ) {
            String userInput;
            // Loop to send messages to the server
            while (true) {
                // Prompt the user to enter a message
                System.out.print("Client: ");
                // Read a message from the console
                userInput = scanner.nextLine();
                // Check if the message is the exit command, and break the loop if it is
                if (userInput.equals("exit")) {
                    out.println(userInput);
                    break;
                }
                // Send the user's message to the server
                out.println(userInput);
                // Receive a message from the server
                String serverResponse = in.readLine();
                // Print the server's message to the console
                System.out.println("Server: " + serverResponse);
            }
        } catch (UnknownHostException e) {
            // Handle the case where the specified host is unknown
            System.err.println("Don't know about host " + hostName);
            System.exit(1);
        } catch (IOException e) {
            // Handle any other exceptions that may occur during the execution of the program
        e.printStackTrace();
        }
    }
}    
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
      ~/java-examples > javac Server.java && java Server                                                                                                   13:45:07
    
      Client: Hi AWS
      Server: Welcome Manohar!
      Client: I am checking TCP connection using Java Program
      Server: Great!
      Client: Its working i am about to leave
      Server: You welcome Bye!. Have a nice day :).
      Client: exit
      Server: exit
    
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
      ~/java-examples > javac Client.java && java Client
    
      Client: Hi AWS
      Server: Welcome Manohar What do you want?
      Client: I am just checking TCP connection using Java Program
      Server: Its Great Working Man!
      Client: Ok I am about to leave
      Server: you Welcome man!
      Client: bye
      Server: Have a nice day!
      Client: exit
    

TCP Connection Establishment using netcat (nc)

In the following example you provided, nc establishes a TCP connection to the server at www.example.com on port 80, which is the default port for HTTP requests. It then sends an HTTP GET request to the server to retrieve the default page (“/”) and specifies the “Host” header to indicate which domain it wants to retrieve the page from.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
~ > nc www.example.com 80 -vvv                                                                                                                       13:10:49
Connection to www.example.com port 80 [tcp/http] succeeded! 👈
GET / HTTP/1.1
Host: www.example.com

HTTP/1.1 200 OK
Accept-Ranges: bytes
Age: 355479
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Wed, 19 Apr 2023 07:41:20 GMT
Etag: "3147526947+gzip"
Expires: Wed, 26 Apr 2023 07:41:20 GMT
Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
Server: ECS (dcb/7EC9)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1256

<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>    
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>

When using nc (netcat) to connect to a TCP server, the following steps occur to establish the connection

  1. nc sends a SYN (synchronize) packet to the server on the specified port number (80 in this case).

  2. The server responds with a SYN-ACK (synchronize-acknowledge) packet, indicating that it received the SYN packet and is willing to establish a connection.

  3. nc sends an ACK (acknowledge) packet back to the server, completing the three-way handshake and establishing the connection.

  4. Now that the connection is established, nc can send data to the server, which in this case is an HTTP GET request.

Note that the -vvv flag in the command enables verbose mode, which displays more information about the connection process and data transmission.


Establishing TCP Connections in Browsers

when you type www.example.com in the browser, the browser will automatically establish a TCP connection with the server that hosts the website.

Model Representation Figure 1 : TCP Connection

The process of establishing a TCP connection typically involves a series of steps, including:

  • The browser resolves the domain name to an IP address using DNS (Domain Name System).
  • The browser sends a SYN (synchronize) packet to the server to initiate the connection.
  • The server responds with a SYN-ACK (synchronize-acknowledge) packet, indicating that it is willing to establish a connection.
  • The browser sends an ACK (acknowledge) packet to confirm the connection.
  • Once the connection is established, the browser can send HTTP requests to the server to retrieve the website content.

All of these steps happen behind the scenes, without the user needing to manually initiate the connection or perform any of the necessary handshaking.


Summary

TCP (Transmission Control Protocol) is a communication protocol used by devices on a network to establish a reliable connection and exchange data. It ensures that data packets are delivered in the correct order and without errors, and also retransmits lost packets to ensure reliable communication. Once communication is complete, the devices terminate the connection. TCP is a crucial component of the internet and other networks, as it ensures reliable communication between devices over the network.

In summary, nc uses the TCP protocol to establish a connection between the client and server, which is used to exchange HTTP messages between them.

This post is licensed under CC BY 4.0 by the author.

Understanding the Fundamentals of Web Server

Dockerizing Your Development Workflow - A Step-by-Step Guide