Echo Server and Client

This past winter was quite long but not too cold. A few weeks ago we received a one two punch with two winter storms. After that the temperatures went up and we had a day with temperatures in the mid 80s. In the past week the temperatures were down. Last night we were in the lower 40s. We turned off the central heating system at home for the season. We have already been using the air conditioner for a few days. This morning the inside temperature upstairs was 66 F. My home office is downstairs. The temperature has been at a solid 60 F so far. My wife and I are planning on going for a walk in a couple hours.

As I have mentioned in previous posts, I am working designing a storage system for DICOM objects. I will continue making posts regarding different aspects of different databases with emphasis on MongoDB.  That said; I also am reviewing Java. I just finished a chapter on networking and decided on a quick post. The networking chapter was part of a class by Infinite Skills, part of O’Reilly’s Safari Books Online.

As usual, I like to experiment with the material. In this case I was implementing and modifying code as I watched the course. I want to refresh networking in general. I am more interested on HTTPS at this time, but you always learn something new. Recently I purchased a couple books in Java, each over 1,000 pages. Will have posts on both later this year.

The idea of this post is to implement a simple echo server and a client to access it. I am a fan of Test Driven Development (TDD) so I started with the client. After I had a basic client I went and implemented the server. In a nutshell the client sends a sentence and the server echoes the exact same message. Yeah I know, not too exciting, but what else can you do a cold Saturday morning when left alone home?

The software was written in Java using the Eclipse Oxygen.3 IDE. I was working on my Windows 10 machine.

Following is a screen capture of a command prompt console showing the echo server in action:

C:\Temp>echoserver

C:\Temp>java -jar c:\temp\EchoServer.jar
<<< waiting for a client connection port: 4444 ...
<<< connected !!!
<<< listening for input ...
<<< line ==>Hello world.<== (1)
<<< line ==>How are you doing today?<== (2)
<<< line ==>Is is nice and sunny!!!<== (3)
<<< line ==>bye<== (4)
<<< closing resources ...
<<< resources closed !!!

The server is invoked using a batch file. The reason for that is to be able to run the server by double clicking or executing a single file. Let me show you the files of interest in my c:\Temp folder:

C:\Temp>dir echoserver*
 Volume in drive C is OS
 Volume Serial Number is 26E8-87B0

 Directory of C:\Temp

05/10/2018  06:37 PM                32 EchoServer.bat
05/12/2018  11:19 AM             9,568 EchoServer.jar
               2 File(s)          9,600 bytes
               1 Dir(s)  644,306,567,168 bytes free

The contents of the EchoServer.bat file follows:

java -jar c:\temp\EchoServer.jar

It is a single line (shown when I typed the name of the batch file). It invokes Java with the specified JAR file which was exported from the Eclipse IDE.

The client is quite similar. The matching run for the echo client follows:

C:\Temp>echoclient

C:\Temp>java -jar c:\temp\EchoClient.jar
<<< connected to host ==>127.0.0.1 port: 4444
>>> text to echo: Hello world.
<<< echo ==>Hello world.<== (1) >>> text to echo: How are you doing today?
<<< echo ==>How are you doing today?<== (2) >>> text to echo: Is is nice and sunny!!!
<<< echo ==>Is is nice and sunny!!!<== (3) >>> text to echo: bye
<<< echo ==>bye<== (4)
<<< closing resources ...
<<< resources closed !!!

I also generated two files as illustrated:

C:\Temp>dir echoclient*
 Volume in drive C is OS
 Volume Serial Number is 26E8-87B0

 Directory of C:\Temp

05/12/2018  10:19 AM                32 EchoClient.bat
05/12/2018  11:24 AM             9,716 EchoClient.jar
               2 File(s)          9,748 bytes
               0 Dir(s)  644,306,567,168 bytes free

The contents of the EchoClient.bat file are displayed in the screen capture of its invocation. The JVM is invoked with the JAR for the echo client generated by the Eclipse IDE.

The Java code for the client follows:

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

/*
 * 
 */
public class Solution {

	/*
	 * Implements a simple echo server client over TCP/IP sockets.
	 */
	public static void main(String[] args) {
		
		// **** ****
		final int	port		= 4444;
		final String host		= "127.0.0.1";
		
		// **** ****
		Socket sock				= null;
		PrintWriter output		= null;
		BufferedReader input	= null;

		// **** ****
		try {
			// **** connect to the echo server ****
			sock = new Socket(host, port);
	
			// **** ****
			System.out.println("<<< connected to host ==>" + host + " port: " + port);
			
			// **** ****
			output 	= new PrintWriter(sock.getOutputStream(), true);
			
			// **** ****
			input 	= new BufferedReader(new InputStreamReader(sock.getInputStream()));
			
		} catch (UnknownHostException ex) {
			System.err.println("<<< UnknownHostException host ==>" + host + "<== port: " + port + " " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} catch (IOException ex) {
			System.err.println("<<< IOException host ==>" + host + "<== port: " + port + " " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);	
		} catch (Exception ex) {
			System.err.println("<<< Exception host ==>" + host + "<== port: " + port + " " + ex.getMessage() + " " + ex.toString()); System.exit(-1); } finally {} // **** **** BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); String line = ""; String echo = ""; // **** loop echoing a line at a time using the echo server **** System.out.print(">>> text to echo: ");
		int lineNumber = 0;
		try {
			while ((line = in.readLine()) != null) {
				
				// **** send the line to the echo server ****
				output.println(line);
				
				// **** read the line from the echo server ****
				echo = input.readLine();
				
				// **** ****
				System.out.println("<<< echo ==>" + echo + "<== (" + ++lineNumber + ")");
				
				// **** check if the line and echo do NOT match ****
				if (!echo.equals(line)) {
					System.err.println("<<< unexpected line ==>" + line + "<== != echo ==>" + echo + "<=="); } // **** determine if we are done **** if (line.toLowerCase().equals("bye")) { break; } // **** prompt user for the next line to echo **** System.out.print(">>> text to echo: ");
			}
			
			// **** ****
			System.out.println("<<< closing resources ...");
			in.close();
			output.close();
			input.close();
			sock.close();
			System.out.println("<<< resources closed !!!");
			
		} catch (IOException ex) {
			System.err.println("<<< IOException " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);	
		} catch (Exception ex) {
			System.err.println("<<< Exception " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);	
		} finally {}

	}

}

The Java code of the server follows:

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

/*
 * 
 */
public class Solution {

	/*
	 * This class implements a simple echo server over TCP/IP sockets.
	 */
	public static void main(String[] args) {

		// **** ****
		final int	port		= 4444;
		
		// **** ****
		ServerSocket serverSock	= null;
		
		// **** instantiate a server socket ****
		try {
			serverSock = new ServerSocket(port);
		} catch (IOException ex) {
			System.err.println("<<< IOException " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} catch (Exception ex) {
			System.err.println("<<< Exception " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} finally {}
		
		// **** ****
		Socket clientSock = null;
			
		// **** wait for a client connection ****
		try {
			// **** ****
			System.out.println("<<< waiting for a client connection port: " + port + " ...");

			// **** accept a client connection ****
			clientSock = serverSock.accept();
			
			// **** ****
			System.out.println("<<< connected !!!");
			
		} catch (IOException ex) {
			System.err.println("<<< IOException " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} catch (Exception ex) {
			System.err.println("<<< Exception " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} finally {}
					
		// **** ****
		try {
			// **** ****
			PrintWriter output 		= new PrintWriter(clientSock.getOutputStream(), true);
			
			// **** ****
			BufferedReader input 	= new BufferedReader(new InputStreamReader(clientSock.getInputStream()));

			// **** ****
			System.out.println("<<< listening for input ...");
			
			// **** loop receiving and echoing text one line at a time ****
			String line		= "";
			int	lineNumber 	= 0;
			while ((line = input.readLine()) != null) {
				
				// **** line received from the client ****
				System.out.println("<<< line ==>" + line + "<== (" + ++lineNumber + ")");
				
				// **** echo the line back to the client ****
				output.println(line);

				// **** check if we are done with the client ****
				if (line.toLowerCase().equals("bye")) {
					break;
				}
			}
			
			// **** ****
			System.out.println("<<< closing resources ...");
			output.close();
			input.close();
			clientSock.close();
			serverSock.close();
			System.out.println("<<< resources closed !!!");
			
		} catch (IOException ex) {
			System.err.println("<<< IOException " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} catch (Exception ex) {
			System.err.println("Exception <<< " + ex.getMessage() + " " + ex.toString());
			System.exit(-1);
		} finally {}

	}

}

If you have comments or questions regarding this or any other post in this blog please do not hesitate and send me a message. I will not use your name unless you explicitly allow me to do so.

Enjoy;

John

john.canessa@gmail.com

Follow me on Twitter:  @john_canessa

Leave a Reply

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

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