Book Image

Learning Network Programming with Java

Book Image

Learning Network Programming with Java

Overview of this book

Network-aware applications are becoming more prevalent and play an ever-increasing role in the world today. Connecting and using an Internet-based service is a frequent requirement for many applications. Java provides numerous classes that have evolved over the years to meet evolving network needs. These range from low-level socket and IP-based approaches to those encapsulated in software services. This book explores how Java supports networks, starting with the basics and then advancing to more complex topics. An overview of each relevant network technology is presented followed by detailed examples of how to use Java to support these technologies. We start with the basics of networking and then explore how Java supports the development of client/server and peer-to-peer applications. The NIO packages are examined as well as multitasking and how network applications can address practical issues such as security. A discussion on networking concepts will put many network issues into perspective and let you focus on the appropriate technology for the problem at hand. The examples used will provide a good starting point to develop similar capabilities for many of your network needs
Table of Contents (16 chapters)
Learning Network Programming with Java
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
Index

Scalability


When the demand on a server increases and decreases, it is desirable to change the resources dedicated to the server. The options available range from the use of manual threads to allow concurrent behavior to those embedded in specialized classes to handle thread pools and NIO channels.

Creating a threaded server

In this section, we will use threads to augment our simple echo server. The definition of the ThreadedEchoServer class is as follows. It implements the Runnable interface to create a new thread for each connection. The private Socket variable will hold the client socket for a specific thread:

public class ThreadedEchoServer implements Runnable {
    private static Socket clientSocket;

    public ThreadedEchoServer(Socket clientSocket) {
        this.clientSocket = clientSocket;
    }
    ...
}

Note

A thread is a block of code that executes concurrently with other blocks of code in an application. The Thread class supports threads in Java. While there are several ways of creating threads, one way is to pass an object that implements the Runnable interface to its constructor. When the Thread class' start method is invoked, the thread is created and the Runnable interface's run method executes. When the run method terminates, so does the thread.

Another way of adding the thread is to use a separate class for the thread. This can be declared separate from the ThreadedEchoServer class or as an inner class of the ThreadedEchoServer class. Using a separate class, better splits the functionality of the application.

The main method creates the server socket as before, but when a client socket is created, the client socket is used to create a thread, as shown here:

    public static void main(String[] args) {
        System.out.println("Threaded Echo Server");
        try (ServerSocket serverSocket = new ServerSocket(6000)) {
            while (true) {
                System.out.println("Waiting for connection.....");
                clientSocket = serverSocket.accept();
                ThreadedEchoServer tes = 
                    new ThreadedEchoServer(clientSocket);
                new Thread(tes).start();
            }

        } catch (IOException ex) {
            // Handle exceptions
        }
        System.out.println("Threaded Echo Server Terminating");
    }

The actual work is performed in the run method as shown next. It is essentially the same implementation as the original echo server, except that the current thread is displayed to clarify which threads are being used:

    @Override
    public void run() {
        System.out.println("Connected to client using [" 
            + Thread.currentThread() + "]");
        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(
                    clientSocket.getInputStream()));
                PrintWriter out = new PrintWriter(
                        clientSocket.getOutputStream(), true)) {
            String inputLine;
            while ((inputLine = br.readLine()) != null) {
                System.out.println("Client request [" 
                    + Thread.currentThread() + "]: " + inputLine);
                out.println(inputLine);
            }
            System.out.println("Client [" + Thread.currentThread() 
                + " connection terminated");
        } catch (IOException ex) {
            // Handle exceptions
        }
    }

Using the threaded server

The following output shows the interaction between the server and two clients. The original echo client was started twice. As you can see, each client interaction is performed with a different thread:

Threaded Echo Server

Waiting for connection.....

Waiting for connection.....

Connected to client using [Thread[Thread-0,5,main]]

Client request [Thread[Thread-0,5,main]]: Hello from client 1

Client request [Thread[Thread-0,5,main]]: Its good on this side

Waiting for connection.....

Connected to client using [Thread[Thread-1,5,main]]

Client request [Thread[Thread-1,5,main]]: Hello from client 2

Client request [Thread[Thread-1,5,main]]: Good day!

Client request [Thread[Thread-1,5,main]]: quit

Client [Thread[Thread-1,5,main] connection terminated

Client request [Thread[Thread-0,5,main]]: So long

Client request [Thread[Thread-0,5,main]]: quit

The following interaction is from the first client's perspective:

Simple Echo Client

Waiting for connection.....

Connected to server

Enter text: Hello from client 1

Server response: Hello from client 1

Enter text: Its good on this side

Server response: Its good on this side

Enter text: So long

Server response: So long

Enter text: quit

Server response: quit

The following interaction is from the second client's perspective:

Simple Echo Client

Waiting for connection.....

Connected to server

Enter text: Hello from client 2

Server response: Hello from client 2

Enter text: Good day!

Server response: Good day!

Enter text: quit

Server response: quit

This implementation permits multiple clients to be handled at a time. Clients are not blocked because another client is using the server. However, it also allows a large number of threads to be created. If there are too many threads in existence, then server performance can degrade. We will address these issues in Chapter 7, Network Scalability.