Java Socket Programming Simplified

Reading Time: 12 minutes

Hi Friends.

Introduction to  Java socket programming

As a programmer, you must go over some advanced concepts other than traditional data-driven apps like building some interfaces and a database and then execute some commands and load some reports.

Network Programming is one important topic if you want to improve your programming skills, So for that, I will introduce you in this article to Network Socket programming in JAVA.

This article is going to help you understand the basics of networks from a programmer’s view. My main goal here is to help you understand the basic TCP/IP communication programmatically and how to create some basic examples in JAVA.

Also, I will go over the HTTP protocol and how messages are exchanged and we will create a simple HTTP server So you can understand the interaction between a browser and the server side application.

Understand Message transfer between applications

 

Before you can understand how socket communication happens, you need to know a bit more details about how a message is transferred from one application to another each residing on a different machine.

So you need to understand how a message is transferred between two computers.

How that message is transferred

Let’s Say we have two machines A and B. And machine A wants to send a message to B.

You need to understand how this message is translated and sent on the wire to the destination so that it can reach machine B.

So In order to send the message, you need to utilize some communication protocols (TCP or UDP).

The following Diagram explains How a message is sent:

Java socket programming

Explanation:

In this scenario, we are sending a message from A to B and we have the Network packet shown:

You can see in the packet we set the protocol we want to use (TCP or UDP)

Also, we need to set the target destination by setting the destination IP address (D IP)

Now How the packet will no which app it have o be sent. here it comes the role of the port number.

The port identifies which application we are using in the destination address.

for that, the Socket is the combination between the IP and the Port number. so The socket holds both information to allow to application communicate.

I think its somehow clear. Please If you had any questions, comment below or open a question in the questions page.

Before we Implement some examples in Java, Let’s see the Socket primitives for TCP/IP and how it works:

Primitive Meaning
Socket Create a new communication endpoint
Bind Attach a local address to a socket
Listen Announce the willingness to accept connections
Accept Block caller until a connection request arrives
Connect actively attempting to establish a connection
Send Send some data over the connection
Receive Recieve data over the connection
Close Release the connection

Socket Programming with TCP

  1. The server creates a listing socket, think about it as the door that clients can enter through and communicate.
  2. The client contacts the server by creating a local TCP socket specifying the Server IP and the destination Port.
  3. A connection will be established if accepted by the server.
  4. When accepted, the server will create a communication socket to communicate with the client.(This  is done to allow multiple client connections)

java socket programmming2

Examples:

For all examples, I will be using Netbeans and you can copy and create your own application(Full Code is written below)

 

Example 1: TCP/IP Socket Programming

 

Server Side code:


import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;
public class SocketEx1_Server {
/*
* A TCP server that runs on port 9090. When a client connects, it
* sends the client the current date and time, then closes the
* connection with that client. */
      public static void main(String[] args) {
           ServerSocket SS_listener;
           try {
                SS_listener = new ServerSocket(9090);
                try{
                while (true) {
                         System.out.println("The server is on..");
                         Socket socket = SS_listener.accept();
                         try {
                           PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
                           out.println(new Date().toString());
                         } finally {
                           socket.close();
                         }
                         }
                  }
               finally {
               SS_listener.close();
                    }
               }
               catch(IOException e){
              }
      }
}

Client Side Code


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class SocketEx1_Client {
public static void main(String[] args) {
      try{
          String serverHostname = new String ("127.0.0.1"); 
          /* Replace the IP with the server IP, keep it if you are testing on the same machine */
          Socket s = new Socket(serverHostname, 9090);
          BufferedReader input = new BufferedReader(new InputStreamReader(s.getInputStream()));
          String answer = input.readLine();
          System.out.println("the response is "+answer);
          System.exit(0);
         }catch(IOException e){
         }
     }
}

 

Example 2: Echo Message Using UDP

UDP is a communication protocol that transmits independent packets over the network with no guarantee of arrival and no guarantee of the order of delivery.

DatagramSockets are Java’s mechanism for network communication via UDP instead of TCP. Java provides DatagramSocket to communicate over UDP instead of TCP. It is also built on top of IP. DatagramSockets can be used to both send and receive packets over the Internet.

Why Use UDP?

UDP is quite different from the more common TCP. But before considering the surface level disadvantages of UDP, it’s important to understand that the lack of overhead can make it significantly faster than TCP.

Apart from speed, we also need to remember that some kinds of communication do not require the reliability of TCP but value low latency instead. The video is a good example of an application that might benefit from running over UDP instead of TCP.

 

Server Side code


import java.io.*;
import java.net.*;
public class EchoServer_Threads extends Thread {
 protected Socket clientSocket;
 public static void main(String[] args) throws IOException {
  ServerSocket serverSocket = null;
  try {
   serverSocket = new ServerSocket(10008);
   System.out.println("Connection Socket Created");
   try {
    while (true) {
     System.out.println("Waiting for Connection");
     new EchoServer_Threads(serverSocket.accept());
    }
   } catch (IOException e) {
    System.err.println("Accept failed.");
    System.exit(1);
   }
  } catch (IOException e) {
   System.err.println("Could not listen on port: 10008.");
   System.exit(1);
  } finally {
   try {
    serverSocket.close();
   } catch (IOException e) {
    System.err.println("Could not close port: 10008.");
    System.exit(1);
   }
  }
 }
 private EchoServer_Threads(Socket clientSoc) {
  clientSocket = clientSoc;
  start();
 }
 public void run() {
  System.out.println("New Communication Thread Started");
  try {
   PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),
    true);
   BufferedReader in = new BufferedReader(
    new InputStreamReader(clientSocket.getInputStream()));
   String inputLine;
   while ((inputLine = in .readLine()) != null) {
    System.out.println("Server: " + inputLine);
    out.println(inputLine);
    if (inputLine.equals("Bye."))
     break;
   }
   out.close(); in .close();
   clientSocket.close();
  } catch (IOException e) {
   System.err.println("Problem with Communication Server");
   System.exit(1);
  }
 }
}

 

Client Side code:


import java.io.*;
import java.net.*;
import java.util.Scanner;

public class UDP_echoClient {

public static void main(String[] args) { Scanner inFromUser=new Scanner(System.in);
try{
String serverHostname = new String ("127.0.0.1");
//BufferedReader inFromUser = new BufferedReader(new
InputStreamReader(System.in));

DatagramSocket clientSocket = new DatagramSocket();

InetAddress IPAddress = InetAddress.getByName(serverHostname);
System.out.println ("Attemping to connect to " + IPAddress + ") via UDP port 9876");

byte[] sendData = new byte[1024]; byte[] receiveData = new byte[1024];
//read from the user and encode the string into a sequernce of bytes
System.out.print("Enter Message: "); String sentence = inFromUser.nextLine(); sendData = sentence.getBytes();
//create the packet to be send
DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 9876);
//send the packet
clientSocket.send(sendPacket);
//prepare a packet to store the received data
DatagramPacket receivePacket =new DatagramPacket(receiveData, receiveData.length);

System.out.println ("Waiting for return packet");
//set timeout
clientSocket.setSoTimeout(1000000);
try {//Client gets a response from the server clientSocket.receive(receivePacket);

//clients gets the details : data/hostaddress/port number
String receviedSentence = new String(receivePacket.getData()); InetAddress returnIPAddress = receivePacket.getAddress(); int port = receivePacket.getPort();

System.out.println ("From server at: " + returnIPAddress + ":" + port);
System.out.println("Recevied Message is " + receviedSentence);
}
catch (SocketTimeoutException ste)
{
System.out.println ("Timeout Occurred: Packet assumed lost"); }
clientSocket.close();
}
catch (UnknownHostException ex) {
System.err.println(ex);
}
catch (IOException ex) { System.err.println(ex);
}

}

}

 

Example3: Handle multiple clients request (using threads)

 

Why use threads in network programming?

The reason is simple, we don’t want only a single client to connect to the server at a particular time but many clients simultaneously. We want our architecture to support multiple clients at the same time. For this reason, we must use threads on the server side so that whenever a client request comes, a separate thread can be assigned for handling each request.

Let us take an example, suppose a Date-Time server is located at a place, say X. Being a generic server, it does not serve any particular client, rather to a whole set of generic clients. Also, suppose at a particular time, two requests arrive at the server. With our basic server-client program, the request which comes even a nano-second first would be able to connect to the server and the other request would be rejected as no mechanism is provided for handling multiple requests simultaneously. To overcome this problem, we use threading in network programming.

 

Server Side


import java.io.*;

import java.net.*;

public class EchoServer_Threads extends Thread

{

protected Socket clientSocket;

public static void main(String[] args) throws IOException

{

ServerSocket serverSocket = null;

try {

serverSocket = new ServerSocket(10008);

System.out.println ("Connection Socket Created");

try {

while (true)

{

System.out.println ("Waiting for Connection");

new EchoServer_Threads (serverSocket.accept());

}

}

catch (IOException e)

{

System.err.println("Accept failed.");

System.exit(1);

}

}

catch (IOException e)

{

System.err.println("Could not listen on port: 10008.");

System.exit(1);

}

finally

{

try {

serverSocket.close();

}

catch (IOException e)

{

System.err.println("Could not close port: 10008.");

System.exit(1);

}

}

}

private EchoServer_Threads (Socket clientSoc)

{

clientSocket = clientSoc;

start();

}

public void run()

{

System.out.println ("New Communication Thread Started");

try {

PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),

true);

BufferedReader in = new BufferedReader(

new InputStreamReader( clientSocket.getInputStream()));

String inputLine;

while ((inputLine = in.readLine()) != null)

{

System.out.println ("Server: " + inputLine);

out.println(inputLine);

if (inputLine.equals("Bye."))

break;

}

out.close();

in.close();

clientSocket.close();

}

catch (IOException e)

{

System.err.println("Problem with Communication Server");

System.exit(1);

}

}

}

 

Client Side

import java.io.*;
import java.net.*;
import java.util.Scanner;
public class EchoClient_Threads {
 public static void main(String[] args) throws IOException {
  String serverHostname = new String("127.0.0.1");
  Socket echoSocket = null;
  PrintWriter out = null;
  BufferedReader in = null;
  try {
   echoSocket = new Socket(serverHostname, 10008);
   out = new PrintWriter(echoSocket.getOutputStream(), true); in = new BufferedReader(new InputStreamReader(echoSocket.getInputStream()));
  } catch (UnknownHostException e) {
   System.err.println("Don't know about host: " + serverHostname);
   System.exit(1);
  } catch (IOException e) {
   System.err.println("Couldn't get I/O for " + "the connection to: " + serverHostname);
   System.exit(1);
  }
  Scanner stdIn = new Scanner(System.in);
  String userInput;
  System.out.println("Type Message (\"Bye.\" to quit)");
  while ((userInput = stdIn.nextLine()) != null) {
   out.println(userInput);
   // end loop
   if (userInput.equals("Bye."))
    break;
   System.out.println("echo: " + in .readLine());
  }
  out.close(); in .close();
  stdIn.close();
  echoSocket.close();
 }
}

 

Example 4: Knock knock

 

Server side:


import java.io.*;
import java.net.*;
import java.util.Scanner;

public class KnockKnockServer {

public static void main(String[] args) {


ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(1092);
}
catch (IOException e)
{
System.err.println("Could not listen on port: 1092.");
System.exit(1);
}

Socket clientSocket = null;
System.out.println ("Waiting for connection.....");
try {
clientSocket = serverSocket.accept();
}
catch (IOException e)
{
System.err.println("Accept failed.");
System.exit(1);
}

System.out.println ("Connection successful");
System.out.println ("Waiting for input.....");
try{
Scanner userInput=new Scanner(System.in);
PrintWriter out = new
PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader( clientSocket.getInputStream()));
do{
String clientdata, inputLine="Knock! knock!"; out.println(inputLine);

clientdata=in.readLine();
System.out.println("Client:"+ clientdata);

while(!clientdata.toLowerCase().equals("who's there?"))
{
out.println("You are supposed to say Who's there?"); clientdata=in.readLine();
}

String fromUser=userInput.nextLine(); out.println(fromUser);

while(!in.readLine().toLowerCase().equals(fromUser.toLowerCase().concat(" who?")))
out.println("You are supposed to say "+fromUser.concat(" who?")); out.println(userInput.nextLine().concat(", Another try?(n to stop)")); char q=in.readLine().charAt(0); if (Character.toLowerCase(q)=='n') break; } while (true);

out.print("Bye");
out.close(); in.close(); clientSocket.close(); serverSocket.close();
}

catch (IOException e) {
}

}
}

 

Client Side:


import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.Scanner;

public class KnockKnockClient {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);


String host=new String("127.0.0.1");//172.23.50.199");

try{
Socket kkSocket = new Socket(host, 1092);
PrintWriter out = new PrintWriter(kkSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new
InputStreamReader(kkSocket.getInputStream()));

String fromServer, fromUser;
while ((fromServer = in.readLine()) != null) { System.out.println("Server: " + fromServer); if (fromServer.equals("Bye.")) break;

fromUser = input.nextLine(); if (fromUser != null) {
System.out.println("Client: " + fromUser); out.println(fromUser);
}

}
System.out.println("Bye received"); out.close(); in.close(); kkSocket.close();
}
catch(Exception e){

System.out.println(e.getMessage());
}

}
}

Leave a Comment

Your email address will not be published. Required fields are marked *