Created
November 3, 2020 15:55
-
-
Save Lakhan-Nad/c7dc0977defcd256a459823ab9600b2a to your computer and use it in GitHub Desktop.
Generic Client-Server program boilerplate code. Easily customizable as per your requirements
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package client; | |
import java.io.Console; | |
import java.util.Scanner; | |
public final class Client { | |
private static Session session; | |
private static Scanner sc; | |
private Client() { | |
// empty constructor | |
} | |
/** | |
* To wait for an confirmation from the command line | |
* @param message The format of message to print | |
* @param args Args represents the data to print | |
*/ | |
public static void waitForEnter(String message, Object... args) { | |
Console c = System.console(); | |
if (c != null) { | |
// printf-like arguments | |
if (message != null) | |
c.format(message, args); | |
c.format(" --Press ENTER to proceed."); | |
c.readLine(); | |
} | |
} | |
/** | |
* The starting point of the client side program | |
* @param args an array of command line inputs | |
*/ | |
public static void main(String[] args) { | |
sc = new Scanner(System.in); | |
String message = "1. For new Connection type: connect <hostname> <port>\n2. newKeys to calculate new permanent Keys\n3. Anything else to exit application\n"; | |
newSession(); | |
} | |
/** | |
* A function to maintain a new client session | |
* It creates a new session and does all key exchange part | |
* The session takes a argument of ip address/hostname and port | |
*/ | |
private static void newSession(String host, int port) { | |
waitForEnter("Send Connection Request To Server?"); | |
session = new Session("localhost", 9001); | |
if(session.connect(){ | |
/** | |
* Write your application specific logic | |
* Create the functions for Session class specific | |
* to your requirements | |
*/ | |
} | |
session.close(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package server; | |
import java.io.*; | |
import java.math.BigInteger; | |
import java.net.Socket; | |
import java.util.Random; | |
public final class ClientThread extends Thread { | |
private final Socket socket; | |
private long maxWait = 2 * 60 * 1000; // 2 minutes | |
DataInputStream in = null; | |
DataOutputStream out = null; | |
ClientThread(Socket socket) { | |
this.socket = socket; | |
} | |
/** | |
* To see if the I/O Channels are available for a given client | |
* and if yes open them | |
*/ | |
private void establishIO() { | |
if (in != null) { | |
try { | |
in.close(); | |
} catch (Exception e) { | |
System.out.println("Unable to close Input Stream"); | |
} | |
} | |
if (out != null) { | |
try { | |
out.close(); | |
} catch (Exception e) { | |
System.out.println("Unable to close Output Stream"); | |
} | |
} | |
try { | |
if (!socket.isInputShutdown()) | |
in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); | |
if (!socket.isInputShutdown()) | |
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); | |
} catch (Exception e) { | |
System.out.println("Unable to open communication streams"); | |
return; | |
} | |
if (in == null || out == null) { | |
System.out.println("Communication Channels Unavailable"); | |
} | |
} | |
/** | |
* To run this particular client thread | |
* Entry point of client communication | |
*/ | |
public void run() { | |
establishIO(); | |
/** | |
* Application Specific Logic | |
*/ | |
close(); | |
} | |
/** | |
* A utility to close the connection and | |
* release the resources | |
*/ | |
private void close() { | |
try { | |
if (socket != null) | |
socket.close(); | |
if (out != null) | |
out.close(); | |
if (in != null) | |
in.close(); | |
} catch (Exception e) { | |
System.out.println("Unable to Close the Connection"); | |
} | |
/* Documentation */ | |
System.out.println("Connection Closed with " + socket.getInetAddress()); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package server; | |
import java.io.IOException; | |
import java.net.ServerSocket; | |
import java.net.Socket; | |
import java.util.ArrayList; | |
public final class Server { | |
private static ServerSocket server; | |
private Server() { | |
// Empty Constructor | |
} | |
/** | |
* A function to check if the required command line arguments were passed or not | |
* It also creates the socket for listening connections. | |
* @param args command line arguments | |
*/ | |
private static void handleArgs(String[] args) { | |
int port; | |
try { | |
port = Integer.parseInt(args[0]); | |
} catch (NumberFormatException e) { | |
System.out.println("Port is not a valid number"); | |
return; | |
} | |
// try creating a ServerSocket | |
try { | |
server = new ServerSocket(port); | |
} catch (Exception e) { | |
System.out.println(e.getMessage()); | |
} | |
} | |
/** | |
* A function that handles a particular client | |
* This function opens a client and returns a thread | |
* @param socket the socket representing a client | |
* @return thread created to handle client | |
*/ | |
private static Thread handleConnection(Socket socket) { | |
System.out.println("Connection request from: " + socket.getInetAddress()); | |
Thread th = new ClientThread(socket); | |
try { | |
th.start(); | |
} catch (Exception e) { | |
return null; | |
} | |
return th; | |
} | |
/** | |
* Main function to start a client running | |
* @param args command line arguments | |
*/ | |
public static void main(String[] args) { | |
handleArgs(args); | |
if (server == null) { | |
System.out.println("Unable to initiate a server"); | |
System.exit(1); | |
} | |
ArrayList<Thread> clientThreads = new ArrayList<>(); | |
/* Documentation */ | |
System.out.println("Server Started At: " + server.getLocalPort()); | |
int connections = 2; | |
/** | |
* The main loop to listen for connections | |
* we can set a limit to no of connections we will | |
* wait for or set it upto resource allows | |
* | |
* The code here take a client connection request and | |
* open a new thread to communicate with client | |
*/ | |
while (connections > 0) { | |
Socket socket = null; | |
try { | |
socket = server.accept(); | |
} catch (Exception e) { | |
System.out.println("Unable to accept request"); | |
} | |
if (socket != null) { | |
Thread newClient = handleConnection(socket); | |
if(newClient != null) | |
clientThreads.add(newClient); | |
else | |
System.out.println("The client connection refused unable to allocate a new thread"); | |
connections--; | |
} else { | |
System.out.println("Connection Error"); | |
} | |
} | |
/** | |
* This code waits for all the client thread to close | |
* before exiting the server program | |
*/ | |
for(int i = 0; i < clientThreads.size(); i++){ | |
try { | |
clientThreads.get(i).join(); | |
}catch (InterruptedException e){ | |
System.out.println("A client thread was interrupted"); | |
} | |
} | |
// Close the server/listening socket | |
if (server != null) { | |
try { | |
server.close(); | |
} catch (IOException e) { | |
System.out.println(e.getMessage()); | |
System.exit(0); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package client; | |
import java.io.BufferedInputStream; | |
import java.io.BufferedOutputStream; | |
import java.io.DataInputStream; | |
import java.io.DataOutputStream; | |
import java.net.Socket; | |
class Session { | |
private Socket socket; | |
private DataOutputStream out; | |
private DataInputStream in; | |
private final String ip; | |
private final int port; | |
/** | |
* @param ip the ip address or host to connect | |
* @param port the port number to identify the process | |
*/ | |
public Session(String ip, int port) { | |
this.ip = ip; | |
this.port = port; | |
} | |
/** | |
* Function called to connect to Server | |
* @return if connection was established or not | |
*/ | |
public boolean connect() { | |
if (socket != null) { | |
try { | |
socket.close(); | |
} catch (Exception e) { | |
System.out.println("Client busy couldn't establish new connection"); | |
} | |
} | |
/* Documentation */ | |
System.out.println("Sending Connection Request To Server"); | |
try { | |
socket = new Socket(ip, port); | |
} catch (Exception e) { | |
System.out.println("Invalid Host or Port provided or no listener"); | |
return false; | |
} | |
return establishIO(); | |
} | |
/** | |
* To check if IO from server is established or not | |
* IO is the input stream and output stream for the | |
* connection from client side. | |
* @return boolean for same | |
*/ | |
private boolean establishIO() { | |
if (socket == null) { | |
System.out.println("Establish a Connection Before"); | |
return false; | |
} | |
if (in != null) { | |
try { | |
in.close(); | |
} catch (Exception e) { | |
System.out.println("Input Channel Error"); | |
return false; | |
} | |
} | |
if (out != null) { | |
try { | |
out.close(); | |
} catch (Exception e) { | |
System.out.println("Output Channel Error"); | |
return false; | |
} | |
} | |
try { | |
out = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); | |
in = new DataInputStream(new BufferedInputStream(socket.getInputStream())); | |
} catch (Exception e) { | |
System.out.println("Unable to open a I/O Channel"); | |
return false; | |
} | |
return true; | |
} | |
/** | |
* Close the connection | |
*/ | |
public void close() { | |
try { | |
if (socket != null) | |
socket.close(); | |
if (in != null) | |
in.close(); | |
if (out != null) | |
out.close(); | |
} catch (Exception e) { | |
System.out.println("Unable to close Resources"); | |
} | |
/* Documentation */ | |
System.out.println("Connection with Server Closed"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment