Echo Server Tutorial

Note: The example code provided here is based on a similar application in Computer Networks: A Top-Down Approach, 5th ed., by Kurose and Ross.

This tutorial provides a simple introduction to network socket programming in Java. The server will listen for incoming TCP socket connections on a specified port number. When a connection is accepted, it will read a single line of ASCII text from the socket, convert it to uppercase, and write the modified line back to the client.

TCPServer.java

package edu.rutgers.sakai.java.net;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * <ol>
 * <li>Listens for connections on a specified port</li>
 * <li>Reads a line from the newly-connected socket.</li>
 * <li>Converts the line to uppercase and responds on the socket.</li>
 * <li>Closes the socket connection and repeats from (1).</li>
 * </ol>
 * 
 * <p>
 * The source code contained in this file is based on the "TCPServer" example
 * program provided by Kurose and Ross in <u>Computer Networking: A Top-Down
 * Approach</u>, Fifth Edition.
 * </p>
 * 
 * @author Robert S. Moore
 * 
 */
public class TCPServer {

	/**
	 * Parses the parameter (listen port) and accepts TCP connections on that
	 * port. Reads a single line from incoming connections, converts to
	 * uppercase, and then responds with the converted text. Closes the
	 * connection after responding.
	 * 
	 * @param args
	 *            <listen port>
	 */
	public static void main(String[] args) {

		// Make sure both arguments are present
		if (args.length < 1) {
			TCPServer.printUsage();
			System.exit(1);
		}

		// Try to parse the port number
		int port = -1;
		try {
			port = Integer.parseInt(args[0]);
		} catch (NumberFormatException nfe) {
			System.err.println("Invalid listen port value: "" + args[1]
					+ "".");
			TCPServer.printUsage();
			System.exit(1);
		}

		// Make sure the port number is valid for TCP.
		if (port <= 0 || port >= 65536) {
			System.err.println("Port value must be in (0, 65535].");
			System.exit(1);
		}

		// Create the socket, returning null if an exception occurs.
		ServerSocket listenSocket = TCPServer.createSocket(port);
		if (listenSocket == null) {
			System.err.println("Unable to create server socket on port " + port
					+ ".");
			System.exit(1);
		}

		// Accept an incoming connection, handle it, then close and repeat.
		while (true) {
			try {
				// Accept the next incoming connection
				final Socket clientSocket = listenSocket.accept();

				// Create the stream wrappers
				BufferedReader userInput = new BufferedReader(
						new InputStreamReader(clientSocket.getInputStream()));
				DataOutputStream userOutput = new DataOutputStream(clientSocket
						.getOutputStream());

				// Read a line from the client
				String origLine = userInput.readLine();
				// Convert to uppercase
				String upperLine = origLine.toUpperCase() + "n";
				// Write out as ASCII and flush
				userOutput.write(upperLine.getBytes("ASCII"));
				userOutput.flush();
				
				// Close both streams, wrappers may not be closed by closing the socket
				userOutput.close();
				userInput.close();
				// Close the accepted connection
				clientSocket.close();

			} catch (IOException ioe) {
				System.err
						.println("Exception occurred while handling client request: "
								+ ioe.getMessage());
				// Sleep 500ms if an exception occurs (prevent CPU spin)
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// Ignored
				}
				continue;
			}

		}

	}

	/**
	 * Creates a TCP socket bound to the specified port number that will
	 * accepting incoming connections.
	 * 
	 * @param port
	 *            the port number that this server should listen on.
	 * @return a new {@code Socket} if the socket is created successfully, else
	 *         {@code null}.
	 */
	private static ServerSocket createSocket(final int port) {
		try {
			ServerSocket listenSocket = new ServerSocket(port);
			return listenSocket;
		} catch (IOException e) {
			System.err
					.println("An exception occurred while creating the listen socket: "
							+ e.getMessage());
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Prints a simple usage string to standard error that describes the
	 * command-line arguments for this class.
	 */
	private static void printUsage() {
		System.err.println("TCPServer requires 1 argument: <Listen Port>");
	}
}