Core Java

Java Socket Programming

This article talks about sockets and socket programming with java examples. It begins with the basics and explains with an example of how they work.

You can also check this tutorial in the following video:

Socket Programming in Java – video

1. Introduction

Java Socket Programming finds itself very useful for peer-to-peer communication between two Java programs running different JVM. It works on a typical request/response model where-in a java program called client invokes another program called as a server, running on another JVM. The client shall send in a request and the server responds with a response. This communication happens over networking protocols such as TCP connection-oriented or connection-less protocols.

2. What is a socket?

A Socket is an access point for a two-way communication. A socket is associated with a port number on which a process is waiting to listen for the requests. Hence, for any socket to start it needs a port to start. Obviously, it is hosted on a machine identified by a hostname and uniquely addressed by an IP.

Let us take an example of a person ordering fruits from a shop. In this case, the Shopkeeper is the server and the person is the client. The person needs a connection to send-in the request directed to the shopkeeper who is listening on a port. In typical communication, any request is to be addressed to a point on the network. This point is called the host and each host has a hostname and an IP address (a unique address on the network). In the network terminologies, the computers know each other through IP addresses, the request (I need apples) is sent in the form of chunks of data called packets.

In Java, the classes to support the socket programming are packaged under java.net. As per Java, the java.net package comes with two classes Socket and ServerSocket for client and server functionalities respectively.

Socket java - Socket Communication
Socket Communication

3. How sockets work?

For a socket communication to take place, a server socket bound to a port in a host is required. The above diagram shows the server starts a server socket with a port and listens to the incoming request. Once the request comes in, a unique socket is created for the client, and the input and output streams are used to interact with the channel created for the client. At the client-side, there is one more socket to initiate a connection to the server and send in the request.

See the java documentation for more information on sockets.

4. Example for Client/Server

In this section, there are two classes – Shopkeeper and Person. Shopkeeper class does the below actions to listen to requests:

  • Creates a server socket, using the port using the constructor.
  • Listens for a connections using the method serverSocket.accept(). This a blocking call and waits till a request comes.
  • Once a request comes, it proceeds to the next set of instructions.
  • Further, it uses OutputStream of the socket object to write to the output.
  • It uses InputStream of the socket object to read the input.
  • The server reads from the input stream, casts it into String and then returns with a response.

This class Shopkeeper.java has a method public void start(int port) which sets up a socket at a particular port.

Here is the code for server.

Shopkeeper.java

/**
package com.javacodegeeks.examples;

import java.io.IOException;

/**
 * Class to accept single request.
 * 
 * @author Shivakumar Ramannavar
 *
 */
public class Shopkeeper {

	private ServerSocket shopSocket;

	/**
	 * Start a server running at the given port.
	 * 
	 * @param port Port at which server starts.
	 */
	public void start(int port) {

		ObjectOutputStream oos = null;

		ObjectInputStream ois = null;

		try {
			shopSocket = new ServerSocket(port);
			System.out.println("Server single-request version listening at port: " + port);
			Socket clientSocket = shopSocket.accept();
			
						// Open an input stream to the socket.
			oos = new ObjectOutputStream(clientSocket.getOutputStream());

			// Open an input stream to the socket.
			ois = new ObjectInputStream(clientSocket.getInputStream());

			String request = (String) ois.readObject();
			
			System.out.println("Client says, " + request);

			if ("Give me 2 apples".equals(request)) {
				oos.writeObject("Take 2 apples");
			} else {
				oos.writeObject("Sorry I dont know what you are saying");
			}
			clientSocket.close();
		} catch (Exception ex) {
			System.err.println("Error starting the server." + ex.toString());
			ex.printStackTrace();
		} finally {
			try {
				if (oos != null)
					oos.close();

				if (ois != null)
					ois.close();
				
				System.out.println("Shutting down...");
				shopSocket.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		Shopkeeper shopKeeper = new Shopkeeper();
		shopKeeper.start(8888);

	}
}

Person class is the client which opens the socket to the server and sends in the “Give me 2 apples”

Here is the code for the client. This class sends request to single-request server (Shopkeeper) and also to the multiple-request server (ShopkeeperScaled refer section 5)

Person.java

/**
 * 
 */
package com.javacodegeeks.examples;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Person class to request for apples.
 * 
 * @author Shivakumar Ramannavar
 *
 */
public class Person {

	public void sendRequest(String hostName, int portNumber, String request) {

		ObjectOutputStream oos = null;
		ObjectInputStream ois = null;

		try {
			// Open a socket.
			Socket requestSocket = new Socket(hostName, portNumber);

			// Open an input stream and output stream to the socket.
			oos = new ObjectOutputStream(requestSocket.getOutputStream());

			// write to socket using ObjectOutputStream
			oos.writeObject(request);

			// read the server response message
			ois = new ObjectInputStream(requestSocket.getInputStream());

			// Read from and write to the stream according to the server's protocol.
			String message = (String) ois.readObject();

			System.out.println("Client : " + request + "\nServer: " + message);

			// Close the streams.
			// Close the socket.
			requestSocket.close();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (oos != null)
					oos.close();

				if (ois != null)
					ois.close();

			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

	}

	/**
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		Person person = new Person();
		person.sendRequest("localhost", 8888, "Give me 2 apples");
		simulateMulipleClients(person);

	}

	private static void simulateMulipleClients(Person person) throws InterruptedException {
		ExecutorService es = Executors.newCachedThreadPool();

		String[] requests = new String[] { "Give me 2 apples", "Give me 2 bananas", };
		
		Thread threads[] = new Thread[requests.length];

		for (int i = 0; i  {
				person.sendRequest("localhost", 9999, request);
			});
			
			threads[i].start();
		}

		Thread.sleep(3000);
		
		System.out.println("Testing done.");
		// Send the final request to stop
		person.sendRequest("localhost", 9999, "stop");
	}
}

5. Accepting multiple requests

In this section, we discuss how to execute sockets in threads and accept multiple requests. Here is another java class ShopkeeperScaled which has a method runServer() which listens to incoming requests in a loop and the method itself, upon getting the request, spawns a thread for processing and completes. However, the interesting part of this Java program is that the above-mentioned method is called in a loop which depends on the shutdown boolean variable which gets set to true when one of the clients send ‘STOP’ message.

In this Java class, a method private void processClient(Socket clientSocket) is introduced to process incoming requests

Here is the listing for the java program accepting multiple requests.

ShopkeeperScaled.java

/**
 * 
 */
package com.javacodegeeks.examples;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

/**
 * Class to accept multiple requests.
 * 
 * @author Shivakumar Ramannavar
 *
 */
public class ShopkeeperScaled {

	ServerSocket shopSocket = null;
	
	boolean shutdown = false;
	
	/**
	 * Start a server running at the given port.
	 * 
	 * @param port Port at which server starts.
	 * @throws IOException
	 */
	public void start(int port) throws IOException {		

		shopSocket = new ServerSocket(port);
		System.out.println("Server multiple-requests version listening at port: " + port);
		System.out.println("Send STOP to shutdown the server.");

		while (!shutdown) { // The server would be shutdown when client sends 'STOP'
			runServer(port, shopSocket);
		}
		
	}

	private void runServer(int port, ServerSocket shopSocket) {
		
		if(shopSocket.isClosed())
			return;
			
		try {			
			Socket clientSocket = shopSocket.accept();

			Thread t = new Thread(() -> {
				processClient(clientSocket);
			});

			t.start();
		} catch(SocketException ex) {
			// Do Nothing!
		} catch (Exception ex) {
			System.err.println("Error starting the server." + ex.toString());
			ex.printStackTrace();
		} finally {
			
		}
	}

	private void processClient(Socket clientSocket) {
		ObjectOutputStream oos = null;

		ObjectInputStream ois = null;

		try {
			// Open an input stream to the socket.
			oos = new ObjectOutputStream(clientSocket.getOutputStream());

			// Open an input stream to the socket.
			ois = new ObjectInputStream(clientSocket.getInputStream());

			String request = (String) ois.readObject();
			
			System.out.println("Client says, " + request);
			
			if ("Give me 2 apples".equals(request)) {
				oos.writeObject("Take 2 apples");
			} if ("stop".equalsIgnoreCase(request)) {
				System.out.println("Shutdown received!");
				oos.writeObject("Thank you!");
				shutdown = true;
			} else {
				oos.writeObject("Sorry I dont know what you are saying");
			}
		} catch (IOException | ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				if (oos != null)
					oos.close();

				if (ois != null)
					ois.close();

				clientSocket.close();
				
				if(shutdown)
					shopSocket.close();
				
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] args) {
		ShopkeeperScaled shopKeeper = new ShopkeeperScaled();
		try {
			shopKeeper.start(9999);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
}

6. Execution

In this section we will execute the programs and see how it is working.

Prerequisites:

  • Java 1.8 installed in the system. Environment variables JAVA_HOME set to the Java location and PATH set to the directory containing javac and java binaries ( %JAVA_HOME%/bin on windows or $JAVA_HOME/bin on Linux machines)
  • Source code zip and downloaded to a location (say, C:\JavaCodeGeeks. This would be different for Linux)
  • Eclipse IDE (Photon Release (4.8.0) is used for this example)

6.1 Execution using eclipse

Step 1: Open the Eclipse IDE.
Step 2: Click On File >> Import.
Step 3: From the “Import” menu select “Existing Projects into Workspace”.

Socket java - Import the JavaSocketProgramming project
Import the JavaSocketProgramming project

Step 4: Click Next.
Step 5: On the next page, click browse and select the root of the example folder (say,C:\JavaCodeGeeks). Click on the “Finish” button.

Choose the Java Socket Programming project
Choose the JavaSocketProgramming project

Step 6: Ensure Package Explorer is loaded and lists all the files as shown in the figure below.
Step 7: Click on src >> com.javacodegeeks.examples >> Shopkeeper.java
Step 8: Right-click on Shopkeeper.java, from the menu, choose
“Run As” >> “Java Application”
Note: This run starts a single-request server a the port 8888.

Run the server- single-request server
Run the server- single-request server

Step 9: Click on src >> com.javacodegeeks.examples >> ShopkeeperScaled.java
Step 10: Right-click on ShopkeeperScaled.java, from the menu, choose
“Run As” >> “Java Application”
Note: This run starts the multiple-request server a the port 9999.

Run the server- multiple-request server
Run the server- multiple-request server

Step 11: Click on src >> com.javacodegeeks.examples >> Person.java
Step 12: Right-click on Person.java, from the menu, choose
“Run As” >> “Java Application”. This starts the client and hits both of the servers.

Run the client
Run the client

6.2 Sample Outputs

Shopkeeper.java – Single-request Server

Server single-request version listening at port: 8888
Client says, Give me 2 apples
Shutting down...

ShopkeeperScaled.java – Multiple-request Server

Server multiple-requests version listening at port: 9999
Send STOP to shutdown the server.
Client says, Give me 2 bananas
Client says, Give me 2 apples
Client says, stop
Shutdown received!

Person.java – the client.

Client : Give me 2 apples
Server: Take 2 apples
Client : Give me 2 bananas
Server: Sorry I dont know what you are saying
Client : Give me 2 apples
Server: Take 2 apples
Testing done.
Client : stop
Server: Thank you!

6. Download the Eclipse Project

Download
You can download the full source code of this example here: Java Socket Programming

Shivakumar Ramannavar

Shivakumar has 16+ years of experience in Java Development, Cloud and also has a lot of passion in Cloud-native Applications and Kubernetes. Shiva has a Bachelor's Degree from Visweswaraiah Technological University, India. Shiva has been involved in the development of IT systems using Java/J2EE, Kubernetes, and has designed tonnes of applications both on-premise and on-cloud. Shiva strongly believes there is a great revolution of cloud-native technologies and that we can create a world of difference through learning, sharing, and caring among the community.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button