Advanced Java : Unit 1-Networking

 

Networking Basics

Computers running on the Internet communicate to each other using either the Transmission Control Protocol (TCP) or the User Datagram Protocol (UDP), as this diagram illustrates:

Example of network communication.

When you write Java programs that communicate over the network, you are programming at the application layer. Typically, you don't need to concern yourself with the TCP and UDP layers. Instead, you can use the classes in the java.net package. These classes provide system-independent network communication. However, to decide which Java classes your programs should use, you do need to understand how TCP and UDP differ.

TCP

When two applications want to communicate to each other reliably, they establish a connection and send data back and forth over that connection. This is analogous to making a telephone call. If you want to speak to Aunt Beatrice in Kentucky, a connection is established when you dial her phone number and she answers. You send data back and forth over the connection by speaking to one another over the phone lines. Like the phone company, TCP guarantees that data sent from one end of the connection actually gets to the other end and in the same order it was sent. Otherwise, an error is reported.

TCP provides a point-to-point channel for applications that require reliable communications. The Hypertext Transfer Protocol (HTTP), File Transfer Protocol (FTP), and Telnet are all examples of applications that require a reliable communication channel. The order in which the data is sent and received over the network is critical to the success of these applications. When HTTP is used to read from a URL, the data must be received in the order in which it was sent. Otherwise, you end up with a jumbled HTML file, a corrupt zip file, or some other invalid information.


Definition: 

TCP (Transmission Control Protocol) is a connection-based protocol that provides a reliable flow of data between two computers.


UDP

The UDP protocol provides for communication that is not guaranteed between two applications on the network. UDP is not connection-based like TCP. Rather, it sends independent packets of data, called datagrams, from one application to another. Sending datagrams is much like sending a letter through the postal service: The order of delivery is not important and is not guaranteed, and each message is independent of any other.


Definition: 

UDP (User Datagram Protocol) is a protocol that sends independent packets of data, called datagrams, from one computer to another with no guarantees about arrival. UDP is not connection-based like TCP.


For many applications, the guarantee of reliability is critical to the success of the transfer of information from one end of the connection to the other. However, other forms of communication don't require such strict standards. In fact, they may be slowed down by the extra overhead or the reliable connection may invalidate the service altogether.

Consider, for example, a clock server that sends the current time to its client when requested to do so. If the client misses a packet, it doesn't really make sense to resend it because the time will be incorrect when the client receives it on the second try. If the client makes two requests and receives packets from the server out of order, it doesn't really matter because the client can figure out that the packets are out of order and make another request. The reliability of TCP is unnecessary in this instance because it causes performance degradation and may hinder the usefulness of the service.

Another example of a service that doesn't need the guarantee of a reliable channel is the ping command. The purpose of the ping command is to test the communication between two programs over the network. In fact, ping needs to know about dropped or out-of-order packets to determine how good or bad the connection is. A reliable channel would invalidate this service altogether.

The UDP protocol provides for communication that is not guaranteed between two applications on the network. UDP is not connection-based like TCP. Rather, it sends independent packets of data from one application to another. Sending datagrams is much like sending a letter through the mail service: The order of delivery is not important and is not guaranteed, and each message is independent of any others.


Note: 

Many firewalls and routers have been configured not to allow UDP packets. If you're having trouble connecting to a service outside your firewall, or if clients are having trouble connecting to your service, ask your system administrator if UDP is permitted.


Understanding Ports

Generally speaking, a computer has a single physical connection to the network. All data destined for a particular computer arrives through that connection. However, the data may be intended for different applications running on the computer. So how does the computer know to which application to forward the data? Through the use of ports.

Data transmitted over the Internet is accompanied by addressing information that identifies the computer and the port for which it is destined. The computer is identified by its 32-bit IP address, which IP uses to deliver data to the right computer on the network. Ports are identified by a 16-bit number, which TCP and UDP use to deliver the data to the right application.

In connection-based communication such as TCP, a server application binds a socket to a specific port number. This has the effect of registering the server with the system to receive all data destined for that port. A client can then rendezvous with the server at the server's port, as illustrated here:

A client communicating to a server through its port

Definition: 

The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer.


In datagram-based communication such as UDP, the datagram packet contains the port number of its destination and UDP routes the packet to the appropriate application, as illustrated in this figure:

Routing the packet to the appropriate application.

Port numbers range from 0 to 65,535 because ports are represented by 16-bit numbers. The port numbers ranging from 0 - 1023 are restricted; they are reserved for use by well-known services such as HTTP and FTP and other system services. These ports are called well-known ports. Your applications should not attempt to bind to them.

Networking Classes in the JDK

Through the classes in java.net, Java programs can use TCP or UDP to communicate over the Internet. The URLURLConnectionSocket, and ServerSocket classes all use TCP to communicate over the network. The DatagramPacketDatagramSocket, and MulticastSocket classes are for use with UDP.

Socket Programming



Java Networking: Socket

In order to connect to a server over the internet (via TCP/IP) in Java, you need to create a java.net.Socket and connect it to the server. 

Creating a Socket

This code example connects to the server with IP address 78.46.84.171 on port 80. Let us assume that server happens to be web server (www.jenkov.com), and port 80 is the web server's port.

Socket socket = new Socket("78.46.84.171", 80);

You can also use a domain name instead of an IP address, like this:

Socket socket = new Socket("jenkov.com", 80);

Writing to a Socket

To write to a Java Socket you must obtain its OutputStream. Here is how that is done:

Socket socket = new Socket("jenkov.com", 80);
OutputStream out = socket.getOutputStream();

out.write("some data".getBytes());
out.flush();
out.close();

socket.close();

That's how simple it is!

We shouldn't forget to call flush() when we really, really want the data sent to the server across the internet. The underlying TCP/IP implementation in our OS may buffer the data and send it in larger chunks to fit with the size of TCP/IP packets.

Reading from a Socket

To read from a Java Socket we will need to obtains its InputStream. Here is how that is done:

Socket socket = new Socket("jenkov.com", 80);
InputStream in = socket.getInputStream();

int data = in.read();
//... read more data...

in.close();
socket.close();

Pretty simple, right?

Keep in mind that we cannot always just read from the Socket's InputStream until it returns -1, as we can when reading a file. The reason is that -1 is only returned when the server closes the connection. But a server may not always close the connection. Perhaps we want to send multiple requests over the same connection. In that case it would be pretty stupid to close the connection.

Instead we must know how many bytes to read from the Socket's InputStream. This can be done by either the server telling how many bytes it is sending, or by looking for a special end-of-data character.

Closing a Socket

When we are done using a Java Socket we must close it to close the connection to the server. This is done by calling the Socket.close() method, like this:

Socket socket = new Socket("jenkov.com", 80);

socket.close();

Java Networking: ServerSocket

Creating a ServerSocket

Here is a simple code example that creates a ServerSocket that listens on port 9000:

ServerSocket serverSocket = new ServerSocket(9000);

Listening For Incoming Connections

In order to accept incoming connections you must call the ServerSocket.accept() method. The accept() method returns a Socket which behaves like an ordinary Java Socket. Here is how that looks:

ServerSocket serverSocket = new ServerSocket(9000);

boolean isStopped = false;
while(!isStopped){
    Socket clientSocket = serverSocket.accept();

    //do something with clientSocket
}

Only one incoming connection is opened for each call to the accept() method.


Closing Client Sockets

Once a client request is finished, and no further requests will be received from that client, we must close that Socket. This is done by calling:

socket.close();

Closing Server Sockets

Once the server is to shut down we need to close the ServerSocket. This is done by calling:

serverSocket.close();

ServerSocket Class Methods

The java.net.ServerSocket class is used by server applications to obtain a port and listen for client requests.

The ServerSocket class has four constructors −

Sr.No.Method & Description
1

public ServerSocket(int port) throws IOException

Attempts to create a server socket bound to the specified port. An exception occurs if the port is already bound by another application.

2

public ServerSocket(int port, int backlog) throws IOException

Similar to the previous constructor, the backlog parameter specifies how many incoming clients to store in a wait queue.

3

public ServerSocket(int port, int backlog, InetAddress address) throws IOException

Similar to the previous constructor, the InetAddress parameter specifies the local IP address to bind to. The InetAddress is used for servers that may have multiple IP addresses, allowing the server to specify which of its IP addresses to accept client requests on.

4

public ServerSocket() throws IOException

Creates an unbound server socket. When using this constructor, use the bind() method when you are ready to bind the server socket.

If the ServerSocket constructor does not throw an exception, it means that your application has successfully bound to the specified port and is ready for client requests.

Following are some of the common methods of the ServerSocket class −

Sr.No.Method & Description
1

public int getLocalPort()

Returns the port that the server socket is listening on. This method is useful if you passed in 0 as the port number in a constructor and let the server find a port for you.

2

public Socket accept() throws IOException

Waits for an incoming client. This method blocks until either a client connects to the server on the specified port or the socket times out, assuming that the time-out value has been set using the setSoTimeout() method. Otherwise, this method blocks indefinitely.

3

public void setSoTimeout(int timeout)

Sets the time-out value for how long the server socket waits for a client during the accept().

4

public void bind(SocketAddress host, int backlog)

Binds the socket to the specified server and port in the SocketAddress object. Use this method if you have instantiated the ServerSocket using the no-argument constructor.

When the ServerSocket invokes accept(), the method does not return until a client connects. After a client does connect, the ServerSocket creates a new Socket on an unspecified port and returns a reference to this new Socket. A TCP connection now exists between the client and the server, and communication can begin.

Socket Class Methods

The java.net.Socket class represents the socket that both the client and the server use to communicate with each other. The client obtains a Socket object by instantiating one, whereas the server obtains a Socket object from the return value of the accept() method.

The Socket class has five constructors that a client uses to connect to a server −

Sr.No.Method & Description
1

public Socket(String host, int port) throws UnknownHostException, IOException.

This method attempts to connect to the specified server at the specified port. If this constructor does not throw an exception, the connection is successful and the client is connected to the server.

2

public Socket(InetAddress host, int port) throws IOException

This method is identical to the previous constructor, except that the host is denoted by an InetAddress object.

3

public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.

Connects to the specified host and port, creating a socket on the local host at the specified address and port.

4

public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.

This method is identical to the previous constructor, except that the host is denoted by an InetAddress object instead of a String.

5

public Socket()

Creates an unconnected socket. Use the connect() method to connect this socket to a server.

When the Socket constructor returns, it does not simply instantiate a Socket object but it actually attempts to connect to the specified server and port.

Some methods of interest in the Socket class are listed here. Notice that both the client and the server have a Socket object, so these methods can be invoked by both the client and the server.

Sr.No.Method & Description
1

public void connect(SocketAddress host, int timeout) throws IOException

This method connects the socket to the specified host. This method is needed only when you instantiate the Socket using the no-argument constructor.

2

public InetAddress getInetAddress()

This method returns the address of the other computer that this socket is connected to.

3

public int getPort()

Returns the port the socket is bound to on the remote machine.

4

public int getLocalPort()

Returns the port the socket is bound to on the local machine.

5

public SocketAddress getRemoteSocketAddress()

Returns the address of the remote socket.

6

public InputStream getInputStream() throws IOException

Returns the input stream of the socket. The input stream is connected to the output stream of the remote socket.

7

public OutputStream getOutputStream() throws IOException

Returns the output stream of the socket. The output stream is connected to the input stream of the remote socket.

8

public void close() throws IOException

Closes the socket, which makes this Socket object no longer capable of connecting again to any server.

InetAddress Class Methods

This class represents an Internet Protocol (IP) address. Here are following useful methods which you would need while doing socket programming −

Method & Description

1.static InetAddress getByAddress(byte[] addr)

Returns an InetAddress object given the raw IP address.

2.static InetAddress getByAddress(String host, byte[] addr)

Creates an InetAddress based on the provided host name and IP address.

3.static InetAddress getByName(String host)

Determines the IP address of a host, given the host's name.

4.String getHostAddress()

Returns the IP address string in textual presentation.

5.String getHostName()

Gets the host name for this IP address.

6.static InetAddress InetAddress getLocalHost()

Returns the local host.

7.String toString()

Converts this IP address to a String.   

TCP/IP Server:

import java.net.*; 

import java.io.*; 


public class Server

//initialize socket and input stream 

private Socket socket;

private ServerSocket server;

private DataInputStream in;


// creates a server and connects it to the given port 

public Server(int port) 

// starts server and waits for a connection 

try

// we start our server

server = new ServerSocket(port); 

System.out.println("Server started"); 


System.out.println("Waiting for a client ..."); 


// we accept the client in the given port

// and create a socket

// we now have an established connection between 

                         // our client and our server on the given socket

socket = server.accept(); 

System.out.println("Client accepted"); 


// takes input from the client socket 

in = new DataInputStream( 

new BufferedInputStream(socket.getInputStream())); 


String line = ""; 


// reads message from client until "Stop" is sent 

while (!line.equals("Stop")) 

try

line = in.readUTF(); 

System.out.println(line); 


catch(IOException ex) 

System.out.println(ex); 

System.out.println("Closing connection"); 


// close connection 

socket.close(); 

in.close(); 

catch(IOException i) 

System.out.println(i); 


public static void main(String args[]) 

Server server = new Server(6664); 


TCP/IP Client:

import java.net.*; 

import java.io.*; 


public class Client 

// We initialize our socket( tunnel )

// and our input reader and output stream

// we will take the input from the user

// and send it to the socket using output stream

private Socket socket;

private BufferedReader input;

private DataOutputStream out;


// constructor that takes the IP Address and the Port

public Client(String address, int port) 

// we try to establish a connection 

try

// creates a socket with the given information

socket = new Socket(address, port); 

System.out.println("Connected"); 


// we 'ready' the input reader 

input = new BufferedReader(new InputStreamReader(System.in));


// and the output that is connected to the Socket

out = new DataOutputStream(socket.getOutputStream()); 

catch(UnknownHostException u) 

System.out.println(u); 

catch(IOException i) 

System.out.println(i); 


// string to read message from input 

String line = ""; 


// keep reading until "Stop" is input 

while (!line.equals("Stop")) 

try

                                // reads the line from the keyboard

line = input.readLine(); 

out.writeUTF(line); // writes it to the output stream

// now we just need to collect the data  

                                // from the socket on our server

catch(IOException i) 

System.out.println(i); 


// close the connection 

try

input.close(); 

out.close(); 

socket.close(); 

catch(IOException i) 

System.out.println(i); 


public static void main(String args[]) 

Client client = new Client("127.0.0.1", 6664); 


Datagram Programming   

Java DatagramSocket and DatagramPacket is a connection-less socket programming model.

                                    




Java implements low-level communication with UDP protocol using two classes: DatagramPacket and DatagramSocket
The DatagramPacket object is the data container, while the DatagramSocket is the mechanism used to send or receive the DatagramPackets.

DatagramPackets can be created using one of the two constructors  as stated below :
	public DatagramPacket (byte ibuf [ ], int length);
	public DatagramPacket (byte ibuf [ ], int length, InetAddress iaddr, int iport);
The first constructor uses only a byte buffer and a length. It is used for receiving data over a DatagramSocket. 
The second constructor adds the target address and port number, which are used by DatagramSocket to determine where the data in the packet will be sent.

There are several methods in this class DatagramPacket for accessing the internal state. They can be called to get the destination address and port number of a packet, as well as the raw data and its length. Following is a summary of each of them.

	public InetAddress getAddress ( ) - returns the destination InetAddress. It is typically used for sending.
	public int getport ( ) - returns the integer destination port number. It is typically used for sending.
	public byte [ ] getData ( ) - returns the byte array of data contained in the datagram. It is used to retrieve data from the datagram after it has been received.
	public int getLength ( ) - returns the length of the valid data contained in the byte array that would be returned from the getData() method.
There is no method in DatagramPacket class to send or receive any datagrams; this functionality is the responsibility of a companion class DatagramSocket. 
It has the following two constructors :
	public DatagramSocket ( );
	public DatagramSocket ( int port );
The first constructor is used to make communication between two ports in the local machine whereas the second constructor is useful to do communication between two non-localized ports. This class has the following methods :
	public void send (DatagramPacket pkt) - takes a DatagramPacket object and sends the datagram's data to the previously defined host and port address. 
	public synchronized void received (DatagramPacket pkt) - takes a DatagramPacket object as a recipient for data gram to be received.
	public synchronized void close( ) - to close the DatagramSocket that established when the communication is completed.
Following is an example to exercise the data, DatagramPacket, and DatagramSocket classes.

Datagram Server:

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.util.Arrays;

public class DGServer {


public static void main(String[] args) throws IOException {

DatagramSocket ds = new DatagramSocket(5252);

byte buf[] = new byte[2];

byte send[] = { 23, 28 };

DatagramPacket dp = new DatagramPacket(buf, 2);


ds.receive(dp);

System.out.println("Received packet data From Client: " +

Arrays.toString(dp.getData()));


DatagramPacket senddp = new DatagramPacket(send, 2,

dp.getAddress(), dp.getPort());

ds.send(senddp);

}


}

Datagram Client:

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Arrays;

public class DGClient
{
public static void main(String[] args) throws IOException
{
// Constructor to create a datagram socket
DatagramSocket socket = new DatagramSocket();
InetAddress address = InetAddress.getByName("localhost");
int port = 5252;
byte buf[] = { 12, 13 };
byte buf1[] = new byte[2];
DatagramPacket dp = new DatagramPacket(buf, 
2, 
address, 
port);
DatagramPacket dptorec = new DatagramPacket(buf1, 2);
// connect() method
socket.connect(address, port);
// send() method
socket.send(dp);
System.out.println("...packet sent successfully....");

// receive() method
socket.receive(dptorec);
System.out.println("Received packet data From Server: " +
Arrays.toString(dptorec.getData()));

// getLocalPort() method
System.out.println("Local Port : " + socket.getLocalPort());

// getLocalAddress() method
System.out.println("Local Address : " + socket.getLocalAddress());

// setSOTimeout() method
socket.setSoTimeout(50);

// getSOTimeout() method
System.out.println("SO Timeout : " + socket.getSoTimeout());
}

}


Comments

Popular posts from this blog

Advanced Java - JDBC

Core Java BCA3

Java Threads