Creating a TCP Connection Between Client-Server in Java

Gaurangjotwani
5 min readAug 10, 2023

--

As computer science students, understanding networking concepts and communication protocols is crucial. In this tutorial, we’ll explore how to establish a TCP connection between two servers using Java. We’ll build a simple example where a client and a server exchange messages over the TCP protocol.

1. Introduction to TCP Connection

TCP (Transmission Control Protocol) is a reliable and connection-oriented protocol used for data communication between devices over a network. It guarantees the delivery of data in the order it was sent and handles any lost or corrupted packets. This makes it suitable for applications where data integrity and order are important, such as file transfers, web browsing, and more.

2. What is a Socket?

A socket is a fundamental concept in computer networking that serves as an endpoint for sending or receiving data across a computer network. It’s a software interface that enables communication between two devices over a network, allowing data to flow between them. Sockets are a crucial building block for creating networked applications, such as client-server systems, where devices exchange information. Sockets can be thought of as the interface through which programs interact with the network. They abstract the complexity of network communication and provide a simple and consistent way for applications to transmit and receive data.

3. Setting Up Server and Client

// TCPServer.java

import java.net.*;
import java.io.IOException;

public class TCPServer {
public static void main(String[] args) throws IOException {
// Here, we create a Socket instance named socket
ServerSocket serverSocket = new ServerSocket(5001);
System.out.println("Listening for clients...");
Socket clientSocket = serverSocket.accept();
String clientSocketIP = clientSocket.getInetAddress().toString();
int clientSocketPort = clientSocket.getPort();
System.out.println("[IP: " + clientSocketIP + " ,Port: " + clientSocketPort +"] " + "Client Connection Successful!");
}
}
// TCPClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;

public class TCPClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("127.0.0.1", 5001), 1000);
System.out.println("Connection Successful!");
}
}
  1. At the heart of our TCP client lies Java’s standard library, with its networking and I/O packages. Importing these packages is our first step toward building the client. The java.io.IOException package handles exceptions related to input and output operations, while java.net.InetSocketAddress and java.net.Socket packages provide the tools necessary for networking.
  2. Sockets serve as the foundation of network communication, enabling data transfer between devices. We instantiate a ServerSocket on port 5001 in TCPServer.java and a Socket in TCPClient.java.
  3. The main difference between a socket and a server socket is their role in communication. A socket can be used on both the client and server sides of a networked application. A server socket (e.g., a ServerSocket instance in Java) is a specialized socket that listens for incoming connections from clients. It’s specifically used by server applications to accept new client connections.
  4. The connect function takes two arguments: an InetSocketAddress representing the server's IP address and port, and a timeout in milliseconds. In our example, we're attempting to connect to the server with IP address "127.0.0.1" (localhost) on port 5001. The timeout is set to 1000 milliseconds (1 second).

4. Compile and Run

Left Side is the Server Side and Right Side is the Client Side. The last line prints a confirmation message to the console, letting us know that the client successfully connected to the server.

5. Passing Messages Between Servers using Java’s DataInputStream and DataOutputStream

In the realm of networking, the ability to exchange data between servers is a fundamental aspect. Java provides powerful tools to achieve this. We will explore how to establish a communication channel between two servers using the DataInputStream and DataOutputStream classes. These classes simplify the process of sending and receiving data over a network connection. We will walk through an example of a client-server interaction where messages are passed back and forth using TCP sockets. Here is the updated Server and Client Code

// TCPServer.java

public class TCPServer {
public static void main(String[] args) throws IOException {
// .... Previous Code...
System.out.println("[IP: " + clientSocketIP + " ,Port: " + clientSocketPort +"] " + "Client Connection Successful!");

DataInputStream dataIn = new DataInputStream(clientSocket.getInputStream());
DataOutputStream dataOut = new DataOutputStream(clientSocket.getOutputStream());

String clientMessage = dataIn.readUTF();
System.out.println(clientMessage);
String serverMessage = "Hi this is coming from Server!";
dataOut.writeUTF(serverMessage);

dataIn.close();
dataOut.close();
serverSocket.close();
clientSocket.close();
}
}
public class TCPClient {
public static void main(String[] args) throws IOException {

System.out.println("Connection Successful!");

// .... Previous Code...

// Passing and Receiving messages
DataInputStream dataIn = new DataInputStream(socket.getInputStream());
DataOutputStream dataOut = new DataOutputStream(socket.getOutputStream());
dataOut.writeUTF("Hello, This is coming from Client!");
String serverMessage = dataIn.readUTF();
System.out.println(serverMessage);

dataIn.close();
dataOut.close();
socket.close();
}
}
  1. We create a DataInputStream and DataOutputStream to handle communication with the server.
  2. We send a message to the server using dataOut.writeUTF().
  3. We read the server’s response using dataIn.readUTF() ().
  4. In both the server and client code examples provided , you might have noticed the use of the socket.close() method. This method is crucial for ensuring that the network connection is properly closed after communication is complete. When you’re finished exchanging data with a client or server, calling close() on the socket helps release resources associated with the connection.

6. Compile and Run

Since we see the two messages printed, it works!

7. Exercise for you — Make it interactive

Congratulations on making it this far in your journey of exploring TCP communication in Java! You’ve already grasped the basics of how servers and clients can exchange messages using sockets and streams. But hey, let’s admit it, our example so far has been a bit… well, limited. I mean, sending just one message and then having the server say, “I’m outta here!” — that’s like a one-liner stand-up comedy routine!

But fear not, we’re about to level up our networking game. Imagine if we could turn this into a real-time interaction, just like a chat! 🚀🎉

Here’s a little teaser for you: How about we use while loops and Java’s Scanner to get user input messages on the fly? Yes, that's right! We're talking about a dynamic conversation that keeps going and going, like a never-ending story. I will leave that for you to implement.

8. Food for Thought

For my self aware audience, I know what you are thinking. Its just one client though, how can we have a multiuser experience? If you are thinking Threads, BANG ON! I will cover that in future tutorial :)

9. Conclusion

Ready for a more advanced networking challenge? Check out my GitHub repository for a comprehensive example that goes beyond our basic app. Explore a server-client application where the server hosts a powerful key store, and clients can connect using TCP and UDP connections. With features like get, put, and delete, you'll witness the real magic of networking in action. Don't miss the chance to delve into a sophisticated use case that showcases the full potential of TCP/UDP communication in Java. Dive in and experience it firsthand: https://github.com/GaurangJotwani/TCP-UDP-Key-Value-Store

Until Next Time, Coder!

--

--