Client server programming is the need of time. We daily use a lot of applications that communicate with the server to fetch the required information. For example: RSS feed client, chat messenger etc. In this tutorial, I will write about network communication, which includes writing clients and servers.

Sockets

Networking programming is based on sockets. A network clients talks to the server using a socket connection. Socket is not a physical one. It is a communication interface between computers. A socket is bound to a port number, which is used by the TCP layer for identification purpose. Java provides java.net.Socket for Socket communication.

Socket class provides following 8 constructors:

Socket()
Socket(InetAddress address, int port)
Socket(InetAddress host, int port, boolean stream)
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
Socket(SocketImpl impl)
Socket(String host, int port)
Socket(String host, int port, boolean stream)
Socket(String host, int port, InetAddress localAddr, int localPort)

Example below creates a socket object bounded to port 2000.

Java Code:
Socket socket = new Socket ("machineName",2000);
Communication protocols

Two protocols can be used for socket programming:

- datagram communication (UDP)
- stream communication


TCP vs UDP

Many developers ask which protocol to use when developing a client server application. Actually it depends on the requirements. Following points should be kept in mind when deciding the protocol for communication:

- TCP connection takes a little time for establishing.
- In UDP, each packet contains socket address which makes the packet heavy.
- There is a size limit of 64 kilobytes on data grams for UDP.
- UDP is unreliable protocol.

Datagram communication

The datagram communication protocol is also called UDP (user datagram protocol). Datagram is defined as:

A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.

UDP is a connectionless protocol. Which means that connection is not maintained throughout the communication. Each time you need to send or receive data from the server, you need to send the socket address with the datagram, which means additional info is being sent in each datagram. It is slower as compared to stream communication.
java.net.DatagramPacket provides two constructors for sending and receiving data.
Java Code:
DatagramPacket(byte[], int) // for receiving 
DatagramPacket(byte[], int, InetAddress, int) // for sending
java.net.DatagramSocket class provides two constructors for creating instance of DatagramSocket.
Java Code:
DatagramSocket()
DatagramSocket(DatagramSocketImpl impl)
DatagramSocket(int port)
DatagramSocket(int port, InetAddress addr)
DatagramSocket(SocketAddress bindaddr)
Creating UDP packet

UDP packet is creating using DatagramPacket. Review the code below:

Java Code:
// to receive data from a remote machine
DatagramPacket packet = new DatagramPacket(new byte[256], 256);
// to send data to a remote machine
DatagramPacket packet =new DatagramPacket( new byte[128], 128, address, port );
Creating UDP Socket

Creating UDP socket is easy. You have to use DatagramSocket class with the required constructor.

Java Code:
// A client datagram socket:
DatagramSocket clientSocket = new DatagramSocket();
// A server datagram socket:
DatagramSocket serverSocket = new DatagramSocket(port);
Listening for UDP packets

Code sample below shows how to listen for UDP packets.
Java Code:
// create datagram packet
. . .
// create datagram server socket
. . .
boolean finished = false;
while ( ! finished ) {
serverSocket.receive (packet);
// process the packet
} 
serverSocket.close();
Processing UDP packets

Processing UDP packets is done using ByteArrayInputStream as shown below:

Java Code:
ByteArrayInputStream bin =new ByteArrayInputStream(packet.getData() );
DataInputStream din =new DataInputStream(bin);
// read the contents of the packet
Sending UDP packets

The code snippet below shows how to send UDP packets.

Java Code:
// create datagram packet
. . .
// create datagram client socket
. . .
boolean finished = false;
while ( ! finished ) {
// write data to packet buffer
clientSocket.send (packet);
// see if there is more to send
}
UDP Example

Java Code:
import java.io.*;
import java.net.*;

class UDPClient
{
public static void main(String args[]) throws Exception
{
BufferedReader inFromUser =
new BufferedReader(new InputStreamReader(System.in));
DatagramSocket clientSocket = new DatagramSocket();
InetAddress IPAddress = InetAddress.getByName("hostname");
byte[] sendData = new byte[1024];
byte[] receiveData = new byte[1024];
String sentence = inFromUser.readLine();
sendData = sentence.getBytes();
DatagramPacket sendPacket =
new DatagramPacket(sendData, sendData.length,IPAddress, 9876);
clientSocket.send(sendPacket);
DatagramPacket receivePacket =
new DatagramPacket(receiveData, receiveData.length);
clientSocket.receive(receivePacket);
String modifiedSentence = new String(receivePacket.getData());
System.out.println("FROM SERVER:" + modifiedSentence);
clientSocket.close();
}
}

Non-blocking I/O receiving UDP packets

It is a good practice to set a time-out in milliseconds to determine how long a read operation blocks, before throwing an exception. Following method is used:

Java Code:
socket.setSoTimeout(duration);
java.io.InterruptedException is thrown if given times is exceeded.

Stream communication

The stream communication protocol is also known as TCP (transfer control protocol). It is a connection-oriented protocol, which means that connection is maintained throughout the communication. First the connection is established between the server and the client, and then the data is sent and received. One can send/receive data as many times as required. The connection will be active throughout. After finishing communication, connection is terminated.

Connection takes place between a pair of sockets. Both the server and the client create sockets for the communication. First the sockets are connected and then the communication takes place.

Stream communication (Server)

Lets do this in an example:

First we will create a server that will wait for the client requests. We will start by declaring a server socket, a client socket and input/output streams. Then we have to open a connection on a port. Usually it is not a wise decision to use port number that is less than 1023 because ports less than 1023 are reserved of OS use. We will create a SeverSocket object and will specify port on which that ServerSocket will be opened. Once we have the ServerSocket object, we will create a client socket object that will wait for the client’s request.

Java Code:
clientSocket = echoServer.accept();
Once the connection is made, streams will be initialized and data transfer can take place. We are trying to get data from user and then simply send connection date/time to the client.

Java Code:
ServerSocket echoServer = null;
String line;
DataInputStream is;
PrintStream os;
Socket clientSocket = null;

try {
echoServer = new ServerSocket(2000);
}
catch (IOException e) {
System.out.println(e);
}

try {
System.out.println("Waiting for the client request ... ");
clientSocket = echoServer.accept();
System.out.println("Request received.");
is = new DataInputStream(clientSocket.getInputStream());
os = new PrintStream(clientSocket.getOutputStream());

os.println("Hi. You connected to the Server at: " + new Date());

line = is.readLine();
System.out.println("Client: "+line);
os.flush();
}
catch (IOException e) {
e.printStackTrace();
}
We are using port 2000 for the communication. If this port is already in use, we will get following exception:

Java Code:
java.net.BindException: Address already in use: JVM_Bind
Now our server is ready and is listening on port 2000. Time to create a client to communicate with the server.

Stream communication (Client)

I will now write a TCP socket client, that will connect to the server which is listening on port 2000. The client will send data to the server and well get connection time stamp from the server.

In the example below, you will learn how to connect to a TCP socket server and how to send and receive data.

First part is to declare client socket and input/output streams. Then we have to connect to the server using socket. While declaring socket object, we have to mention the host name and the port on which the server is listening. Once the connection is made, we will open streams and data exchange will take place.

Java Code:
Socket smtpSocket = null;
DataOutputStream os = null;
DataInputStream is = null;

try {
smtpSocket = new Socket("nbooknm", 2222);
os = new DataOutputStream(smtpSocket.getOutputStream());
is = new DataInputStream(smtpSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host: hostname");
} catch (IOException e) {
System.err.println("Couldn't get I/O for
the connection to: hostname");
}

if (smtpSocket != null && os != null && is != null) {
try {
os.writeBytes("Hello Server");
os.writeBytes("Please help me.");
os.flush();
String responseLine;
while ((responseLine = is.readLine()) != null) {
System.out.println("Server: " + responseLine);
break;
}
os.close();
is.close();
smtpSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to
unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException:  " + e);
}
}
Output:
Java Code:
Server: Hi. You connected to the Server at: Mon Dec 26 14:57:02 CET 2007
You will get UnknownHostException if hostname is not found and you will get IOException if port is incorrect. So exception handling is important to inform the user incase of failed connection.

Getting clients address

Sometimes it is useful to get the client’s address. This can be stored in database or in XML file for record. For instance: who connected to the server and when? Following code prints the client’s address.

Java Code:
clientSocket = echoServer.accept();
System.out.println("Request received from ." + clientSocket.getInetAddress());
Using ObjectInputStream/ObjectOutputStream

In the previous examples, we used DataInputStream and DataOutputStream. We can also use Object streams for client server communication. In that case, we have to use object streams on both sides that is: client and server. By doing so, the entire communication will be done in form of objects. This means, we can send anything to the server because everything is an object. An interesting example would be sending file. Now lets rewrite the echo server and its client using object streams.

Server

Java Code:
ServerSocket echoServer = null;
String line;
ObjectInputStream is;
ObjectInputStream ois;
//PrintStream os;
ObjectOutputStream os;
Socket clientSocket = null;

try {
echoServer = new ServerSocket(2222);
}
catch (IOException e) {
System.out.println(e);
}

try {
System.out.println("Waiting for the client request ... ");
clientSocket = echoServer.accept();
System.out.println("Request received from ." + clientSocket.getInetAddress());
//is = new DataInputStream(clientSocket.getInputStream());

ois = new ObjectInputStream(clientSocket.getInputStream());
os = new ObjectOutputStream(clientSocket.getOutputStream());

System.out.println("Hi. You connected to the Server at: " + new Date());

Object clientMsg = ois.readObject();
System.out.println("Client: "+clientMsg.toString());
os.writeObject("Sever confirmation");
os.flush();
}
catch (IOException e) {
e.printStackTrace();
}
Client

Java Code:
Socket smtpSocket = null;
ObjectOutputStream os = null;
ObjectInputStream is = null;

try {
smtpSocket = new Socket("nbooknm", 2222);
os = new ObjectOutputStream(smtpSocket.getOutputStream());
is = new ObjectInputStream(smtpSocket.getInputStream());
} catch (UnknownHostException e) {
System.err.println("Don't know about host: hostname");
} catch (IOException e) {
System.err.println("Couldn't get I/O for the connection to: hostname");
}

if (smtpSocket != null && os != null && is != null) {
try {
os.writeObject("Hello server. Please help me.");
os.flush();
String responseLine;
while ((responseLine = is.readObject().toString()) != null) {
System.out.println("Server: " + responseLine);
break;
}
os.close();
is.close();
smtpSocket.close();
} catch (UnknownHostException e) {
System.err.println("Trying to connect to unknown host: " + e);
} catch (IOException e) {
System.err.println("IOException:  " + e);
e.printStackTrace();
}
}
Console on server:
Java Code:
Waiting for the client request ... 
Request received from ./192.168.0.87
Hi. You connected to the Server at: Thu Dec 27 17:36:29 CET 2007
Client: Hello server. Please help me.
Console on client:
Java Code:
Server: Sever confirmation

Sending file to the server

If you want to send files from a client to a TCP server, you have to use object streams. Use ObjectInputStream at server side for receiving the file and use ObjectOutputStream on the client side to send the file. Just to revise things, File is an object.

Client
Java Code:
Object clientMsg = ois.readObject();
File file = (File)clientMsg;

Server
Java Code:
File file = new File("C:\\simple.zip");
os.writeObject(file);
os.flush();

Conclusion

Developing client server applications is not difficult using Java. The two available options are TCP and UDP. Both have their positives and negatives. Which protocol to use depends on the requirements and the environment.

I have explained TCP and UDP protocols for communication with examples. You should try these at your end and should try to play around. Dig deep and play around. Happy coding.