14 Networking — Java Programming
14.1 Introduction
The java programming language has become the premier tool for connecting computers over the internet and corporate Intranets. Networking concepts and Network programming using Java are introduced in this chapter
14.2 Networking basics
A network socket is like an electrical socket. Any object that understands the standard ways of communicating with the socket can plug in and communicate with it. TCP/IP is a suite of communication protocols used to connect network devices on the internet.
14.2.1 TCP/IP model
TCP/IP stands for Transmission Control Protocol/Internet Protocol. The TCP/IP model is shown in the figure below.
| TCP/IP Model |
| Application Layer |
| Transport Layer |
| Network Layer |
| Physical Layer |
Internet Protocol(IP) is a low level routing protocol that breaks data into small packets and sends them to an address across a network. Transmission control protocol (TCP) is a higher-level protocol that manages to robustly string together these packets, sorting and re-transmitting them as necessary to reliably transmit your data. A third kind of protocol called Used Diagram Protocol(UDP) can be used directly to support fast, connectionless, unreliable transport of packets.
The most common words we come across when studying networking are the server and the client. A server is anything that has some resource that can be shared. There are many servers like compute servers, print servers, disk servers, web servers etc. A client is simply any other entity that wants to gain access to a particular server. The server is considered to be a permanently available resource, while the client is free to disconnect from the server after it has been served. A server can serve many different clients at once, as well as serve many different types of information. This is managed by a port. A port is a numbered socket on a particular machine. A server is allowed to accept multiple clients, connected to the same port, although each session is unique. To manage multiple clients, a server process must be multithreaded or have some other means of multiplexing the simultaneous input and output.
TCP/IP reserves the lower 1024 ports for specific protocols. For example, port number 21 is reserved for FTP, 23 for Telnet, 80 for HTTP etc. It is up to each protocol to determine how a client should interact with the port. Every computer on the Internet has an address. An Internet address is a number that uniquely identifies each computer on the Net. There are 32 bits in an IP address, and we often refer to them as sequence of four numbers between 0 to 255 seperated by dots. The first few bits define which class of network. There are 5types of classes of network named A,B,C,D and E. The last byte in the address identifies the computer uniquely. This scheme allows for half a billion devices to live on class C networks. The class C network is one in which most of the Internet users are present. There are over two million networks in C class.
Java supports TCP/IP both by extending the already established stream I/O interface and by adding the features required to build I/O objects across the network. Java supports both TCP and UDP protocol families. TCP is sed for reliable stream-based I/O across the network. UDP supports a simpler, hence faster, point-to-point datagram-oriented mode. There are many classes defined in the java.net package. These classes can be used in different ways to accomplish different ways of communication. The InetAddress class is used to encapsulate both the numerical IP address and the domain name for that address.
The InetAddress class has no visible constructors to create an InetAddress object you have to use one of the static methods that return an instance of a class. The three methods getLocalHost(), getByName(), getAllByName() can be use to create instances of InetAddress. The getLocalHost() method simply returns that InetAddress object that represents the local host. The getAllByName() method returns an array of InetAddress that represent all of the address that a particular name resolve name resolves to. If these methods are unable to resolve the host name, they throw an UnknownHostException.
//Program 14.1 to print address of the local host //AddressTest.java
import java.net.*; class AddressTest { public static void main(String[] args) { try { InetAddress add = InetAddress.getLocalHost(); System.out.println(add); } catch(Exception ex) { System.out.println("An error occurred when trying to get host address"); } } } /* Output: C:\java\bin\javabook>java AddressTest
LAPTOP-BOPQKI3U/192.168.29.81
*/
Program 14.2 Program to find address of the host whose domain name is known.
//RemAddressTest.java
import java.net.*; class RemAddressTest { public static void main(String[] args) { try { InetAddress add = InetAddress.getByName("rediff.com"); System.out.println(add); } catch(Exception ex) { System.out.println("An error occurred when trying to get host address"); } } }
/* Output C:\java\bin\javabook>java RemAddressTest
rediff.com/23.52.40.72
*/
14.3 Sockets
TCP/IP sockets are used to implement reliable, bi-directional, persistent, point-to-point, and stream-based connections between hosts on the Internet. A socket can be used to connect to Java’s I/O system to other programs that may reside either on the local machine or on any other machine on the Internet. There are two kinds of TCP sockets in Java. One is for servers and the other is for clients. The ServerSocket class is designed to be a listener, which waits for clients to connect before doing anything. The socket class is designed to connect to server sockets and initiate protocol exchanges. The creation of the socket object implicity establishes a connection between the client and server. There are no methods or constructors that explicitly expose the details of establishing that connection. There are two constructors used to create client sockets.
|
Socket(String hostname, int port) |
creates a socket connecting the localhost to the named host and port. Throws an UnknowHostException or an IOException |
|
Socket(InetAddress ipaddress, int port) |
Creates a socket using a pre-existing InetAddress object and a port, can throw IOException. |
A socket can be examined at any time for the address and port information associated with it, using getInetAddress(), getPort(), getLocalPort() methods. Once the socket has been related, it can also be examined to gain access to input and output streams associated with it by using the methods getInptStram() and getOutputStream(). Each of these methods can throw an IOException. The streams can be closing using the close() method.
As we mentioned earlier, Java has a different socket class that must be used for creating server applications. The ServerSocket class is used to create servers that listen for either local or remote client programs to connect to them on published ports. ServerSocket are quite different from normal socket as having an interest in client connections. The constructors for ServerSocket reflect the port that you wish to accept connections and the number of clients that can be kept pending before it refuses the connections The default value is 50 The constructors might throw an IOException under adverse condition. The constructors are as follows
|
ServerSocket(int port) |
Creates server socket on the specified port with a queue length of 50 |
|
ServerSocket(int port, int maxqueue) |
Creates a serer socket on the specified port with maximum queue length of maxqueue |
|
ServerSocket(int port, int maxqueue, InetAddress localaddress) |
Creates a server socket on the specified port with multihomed host, localaddress specified the IP address to which this socket binds |
Program 14.3 Program for implementing a Server using Java Sockets
//MessageServerold.java
import java.net.*; import java.io.*; class MessageServer { private static int port = 4321; public static void main(String[] args) { try (ServerSocket ss = new ServerSocket(port)) { System.out.println("Server started and waiting for a client connection on port " + port); try (Socket s = ss.accept()) { System.out.println("Client connected to the server"); try (PrintWriter out = new PrintWriter(s.getOutputStream(), true)) { out.println("This is a message from the server"); System.out.println("Message sent to client"); } } } catch (IOException e) { System.out.println("There is an error in I/O: " + e.getMessage()); } } }
/* Output: C:\>java MessageServer Client connected to the server Message sent to client */
The simplest way to connect to the above server is through the telnet program. First run the server program on a machine. Then run the telnet program in the client machine. To start telnet in windows. Press the start button and the select Run. In the address box type telnet and then press enter. In the telnet window select Connect and then select Remote System, in the Host Name option, type the address of the host computer running the server program. If you are running the server program running on a local machine you can give localhost or 127.0.0.1. In the port option, type 4321. This is the port number that our server waits for the clients to connect. This number is specified when the server socket is created. You can change it to any other port number that is greater than 1024. The server opens an output stream for the socket and sends the message to the client connected. The telnet program automatically reads this message and displays in its window. The server stops after sending the message, so all the clients connected will be disconnected. Because of this reason the telnet program displays a message saying “Connection to host lost”. It should be noted that the server program we have just written accepts only one client. It stops execution after one client is connected and serviced.
Now let us write our own client program MessaheClient.Java which connects to this server. The client program should explicitly open an input stream and try to read the message from the stream. Similarly if the client sends some information to the server it should open an output stream and print message into that stream from which the server can read the data at a later time.
Program 14.4 Program to implement Client using Java Sockets //MessageClient.java
import java.net.*; import java.io.*; import java.net.InetAddress; class MessageClient { public static void main(String[] args) { try { InetAddress host = InetAddress.getLocalHost(); Socket s = new Socket(host.getHostName(), 4321); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); System.out.println(in.readLine()); in.readLine(); } catch(UnknownHostException uhexcp) { System.out.println("Host computer unknown"); } catch(IOException ioexcp) { System.out.println("An error occured in i/o"); } } }
/* Output: C:\>java MessageClient This is a message from the server */
To execute the example, first run the server on your machine. Then run the client program, If you are running the server and the client on the same machine you can give this name as “localhost”. The port number 4321 is the port on which the server is waiting for the clients to connect.
Program 14.5 Client-Server program
//MessageServer.java
import java.net.*; import java.io.*; class MessageServer1 { private static int port = 2448; // Define the port public static void main(String[] args) { try (ServerSocket ss = new ServerSocket(port)) { System.out.println("Server started and waiting for a client connection on port " + port); try (Socket s = ss.accept()) { System.out.println("Client connected to the server"); try (PrintWriter out = new PrintWriter(s.getOutputStream(), true)) { out.println("This is a message from the server"); System.out.println("Message sent to client"); } } } catch (IOException e) { System.out.println("There is an error in I/O: " + e.getMessage()); } } }
//MessageClient.java import java.net.*; import java.io.*; class MessageClient1 { public static void main(String[] args) { try { Socket s = new Socket(InetAddress.getByName("localhost"), 2448); try (BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()))) { System.out.println(in.readLine()); } s.close(); } catch (UnknownHostException uhexcp) { System.out.println("Host computer unknown: " + uhexcp.getMessage()); } catch (IOException ioexcp) { System.out.println("An error occurred in I/O: " + ioexcp.getMessage()); } } } /* Server Output: C:\>java MessageServer Server started and waiting for a client connection on port 2448 Client connected to the server Message sent to client /* Client Output: C:\>java MessageClient This is a message from the server */
To serve multiple clients simultaneously the server should be multithreaded. It can be implemented by creating a thread for each client that is connected to the thread. Each thread serves one client.
Program 14.6 Echo Server and client program
//EchoServer.java import java.net.*; import java.io.*; class EchoServer extends Thread { private Socket sock; private int clientNumber; EchoServer(int clientNumber, Socket sock) { this.sock = sock; this.clientNumber = clientNumber; } public static void main(String[] args) { int clientCount = 0; try (ServerSocket ss = new ServerSocket(2448)) { System.out.println("Server running on port 2448"); while (true) { Socket incoming = ss.accept(); System.out.println("Client " + clientCount + " connected"); EchoServer serverThread = new EchoServer(clientCount++, incoming); serverThread.start(); } } catch (IOException ex) { System.out.println("Exception occurred: " + ex.getMessage()); } } @Override public void run() { try ( BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream())); PrintWriter out = new PrintWriter(sock.getOutputStream(), true) ) { String str; while ((str = in.readLine()) != null) { if (str.equals("Quit")) break; out.println("echo: " + str); } } catch (IOException ex) { System.out.println("An I/O error has occurred: " + ex.getMessage()); } finally { try { sock.close(); } catch (IOException ex) { System.out.println("Failed to close socket: " + ex.getMessage()); } } } } //EchoClient.java import java.net.*; import java.io.*; class EchoClient { public static void main(String[] args) { try (Socket s = new Socket(InetAddress.getByName("localhost"), 2448); BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream())); PrintWriter out = new PrintWriter(s.getOutputStream(), true); BufferedReader userInput = new BufferedReader(new InputStreamReader(System.in)) ) { String input; System.out.println("Type 'Quit' to exit."); while (true) { System.out.print("Enter message: "); input = userInput.readLine(); if (input.equals("Quit")) { out.println(input); break; } out.println(input); System.out.println("Server response: " + in.readLine()); } } catch (IOException ex) { System.out.println("An I/O error has occurred: " + ex.getMessage()); } } } /* Output: C:\>java EchoServer Server running on port 2448 Client 0 connected Client 1 connected /* C:\>java EchoClient Type 'Quit' to exit. Enter message: hai Server response: echo: hai Enter message: how Server response: echo: how Enter message: are Server response: echo: are Enter message: you Server response: echo: you Enter message: Quit */
This server runs indefinitely and waits for the hosts to arrive at the port 2448. When a client arrives, a new thread is created and client is serviced through the thread. Meanwhile the main method waits for new clients to connect to this server is through telnet. By default the message that you type in the telnet window will not appear. So you should check the option for Local Echo in the Terminal/Preferences menu. You can disconnect from the server by typing Quit(case sensitive) in the telnet window. You can run multiple telnet programs and connect to the server simultaneously. This idea can be extended to amke the server more complex and do some useful work.
Diagram
14.4 Summary
Internet is the network of networks. Java has reached the current heights only because of Internet. In this chapter, Networking concepts are discussed. Simple programs of how to connect to a server, running the server, the clients, connecting to server through telnet are introduced.