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:
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.
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 andPATH
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”.
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.
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.
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.
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.
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
You can download the full source code of this example here: Java Socket Programming