Communicating With Remote Systems Using UDP

Introduction

By now, we know about specifying an Internet destination with the help of the instances of InetAddress class, but the question is how can you communicate with the remote systems? The problem is solved in several ways through java.net package.

Let us see how we can communicate with remote systems using UDP datagrams. One cannot guarantee whether the sent or received datagrams reach their destinations. UDP is mainly useful when you want to broadcast or transmit low-value information on a frequent basis, so losing communication now and then does not affect the service. For guaranteed delivery of data, TCP is used.

The java.net package provides two classes namely DatagramPacket & DatagramSocket by which you can communicate with remote systems.

The DatagramPacket class

The Datagram packets are used to implement a connectionless packet delivery service. The class DatagramPacket defines two constructors which allows you to create datagram packets.

DatagramPacket(byte[] buf, int length)

Construct a DatagramPacket for receiving packets of length

DatagramPacket(byte[] buf, int length, InetAddress address, int port)

Constructs a datagram packet for sending packets of length to the specified port number on the specified host.

The first constructor is used for receiving data over a DatagramSocket.

DatagramPacket(byte buffer, int size)

The second constructor is used for transmitting datagrams. This constructor requires the destination machine’s address and the port number apart from the buffer and the size parameters.

DatagramPacket(byte buffer, int size, InetAddress destination, int port)

Other methods defined in the class DatagramPacket are used for accessing the internal state of a datagram packet.

InetAddress getAddress()

Returns the destination machine’s address.

int getPort()

Returns the port number.

byte[] getData

Returns the data contained in the datagram.

int getLength()

Returns the length of the valid data contained in the byte array returned from the getData() method.

The DatagramPacket class does not provide the mechanism for sending and receiving datagrams. The comparison class, DatagramSocket, provides the functionality.

The DatagramSocket class

The DatagramSocket class provides the functionality for sending and receiving the Datagram, Socket class. This class defines the three constructors,

DatagramSocket()

Constructs a datagram socket and binds it to any available port on the local host machine.

DatagramSocket(int port)

Constructs a datagram socket and binds it to the specified port on the local host machine.

DatagramSocket(int port, InetAddress Iaddr)

Creates a datagram socket, bound to the specified local address.

The important methods defined in this class as,

void send(DatagramPacket packet)throws IOException

This method sends the datagram’s data to the previously defined host and port by taking a DatagramPacket object as a Parameter.

void receive(DatagramPacket packet)throws IOException

This method receives a datagram by taking a DatagramPacket object as a parameter. To extract data from the received datagram, use the getData() method defined in the DatagramPacket class.

void close()

This method closes the opened datagram socket.

Writing Client/Server Systems using UDP

To write Server Systems using UDP, you have to follow the following basic steps,

Step 1

You have to create the datagram socket on a specific port.

Step 2

Invoke the receive() method to wait for incoming packets.

Step 3

According to the agreed protocol, respond to received packets.

Step 4

Repeat step 2 or continue to Step 5.

Step 5

Close the datagram socket.

The following program is a simple datagram server which receives and sends the packets from clients.

//UDPServer.java
// A simple server based on UDP
import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class UDPServer {
    public static void main(String args[]) throws Exception {
        DatagramSocket ds = new DatagramSocket(10000);
        DatagramPacket p1, p2;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        byte arr[] = new byte[255];
        String input, output;
        do {
            arr = new byte[255];
            p1 = new DatagramPacket(arr, 255);
            //receiving data packet
            ds.receive(p1);
            arr = p1.getData();
            input = new String(arr);
            //displaying message
            System.out.print("Message from Client:\t");
            System.out.println(input);
            if (input.charAt(0) == '*') {
                break;
            }
            System.out.println("Enter your message:\t");
            output = br.readLine();
            arr = output.getBytes();
            p2 = new DatagramPacket(arr, arr.length, p1.getAddress(), p1.getPort());
            ds.send(p2); //sending data packet
        } while (true);
        ds.close();
    }
}

To write Client Systems, using UDP, you have to follow the following basic steps,

Step 1

Create the datagram socket on any available port.

Step 2

Create the address to send data

Step 3

Send the data according to the server’s protocol

Step 4

Wait for incoming data

Step 5

Go back to step 3, or step 4 or go to step 6

Step 6

Close the datagram socket

The following program shows a simple datagram client. It reads user input strings and sends them to the echo server presented in the above program. The echo server sends the data right back, and the clients prints the response to the console.

//UDPClient.java
// A simple client based on UDP
import java.io.*;
import java.net.*;
import java.awt.*;
import java.applet.*;
import java.awt.event.*;
public class UDPClient {
    public static void main(String args[]) throws Exception {
        DatagramSocket ds;
        DatagramPacket p1, p2;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        byte arr[] = new byte[255];
        String input, output;
        InetAddress i = InetAddress.getLocalHost();
        output = "Heyy, I m client, Send me Message";
        arr = output.getBytes();
        p1 = new DatagramPacket(arr, arr.length, i, 10000);
        ds = new DatagramSocket();
        //Sending Message
        ds.send(p1);
        do {
            arr = new byte[255];
            p1 = new DatagramPacket(arr, 255);
            //receiving message
            ds.receive(p1);
            arr = p1.getData();
            input = new String(arr);
            System.out.print("Message from Server:\t");
            System.out.println(input);
            if (input.charAt(0) == '*') {
                break;
            }
            System.out.println("Enter your message:\t");
            output = br.readLine();
            arr = new byte[255];
            arr = output.getBytes();
            p2 = new DatagramPacket(arr, arr.length, i, 10000);
            ds.send(p2); //sending message
        } while (true);
        ds.close();
    }
}

Summary

Java is the first programming language developed with built-in support for network programming. This is possible with the help of the classes defined in java.net package. Every time data is transmitted over the network, the process of transmission has to be broken down into discrete steps, and each step must follow rules and protocols. A server process can listen to a port only when a client connects to it. A server can accept multiple clients connected to the same port number, although each session is unique. A server process must be multithreaded to manage multiple client connections.