Low-Level Networking: Sockets
TCP/IP Socket (Connection-Oriented)
A TCP/IP socket provides reliable endpoint for two-way communication between two programs (client-server) running on a network. It combines an IP address with a port number, creating a unique address for a specific process on a specific machine.
A socket holds the following key information to manage a connection:
Local IP Address and Port: The address and port of the machine the socket is on.
Remote IP Address and Port: The address and port of the machine the socket is connected to.
Protocol: The transport protocol being used, which in this case is TCP (Transmission Control Protocol).
Client Sockets (Socket
)
The Socket
class is used by a client to connect to a server. Creating a Socket
object establishes a connection, allowing the program to send and receive data through InputStream
and OutputStream
objects.
Socket(String hostName, int port)
: Creates a socket connected to the specified host and port.Socket(InetAddress ipAddress, int port)
: Connects to a givenInetAddress
and port.
InputStream
and OutputStream
for a socket can be gotten using getInputStream()
and getOutputStream()
respectively. Other methods include isConnected()
, isBound()
, isClosed()
, and close()
.
Server Sockets (ServerSocket
)
The ServerSocket
class is used by a server to listen for incoming connection requests from clients. When creating a ServerSocket
, it registers itself with the system to listen for client connections on a specific port.
When a client connects, the ServerSocket
creates a dedicated Socket
object to handle communication with that client.
Queue length can be specified, which is the number of client connections the system can keep pending before refusing new ones; the default is 50.
ServerSocket(int port)
: Creates a server socket on a port with a default queue length of 50.ServerSocket(int port, int maxQueue)
: Creates a server socket with a specified maximum pending connection queue.
Steps to Establish a TCP Connection
Establishing a TCP connection involves a "three-way handshake" to ensure both the client and server are ready to communicate.
Server Starts and Listens: The server application creates a
ServerSocket
bound to a specific port and calls itsaccept()
method. This puts the server in a listening state, waiting for a client to connect.Client Requests Connection: The client application creates a
Socket
object, specifying the server's IP address and the port number the server is listening on. This action sends a connection request packet (SYN) to the server.Server Accepts Connection: When the server's
accept()
method receives the client's request, it creates a newSocket
dedicated to communicating with that specific client. The originalServerSocket
goes back to listening for other new clients. The server sends an acknowledgment packet (SYN-ACK) back to the client.Connection is Established: The client receives the server's acknowledgment and sends its own final acknowledgment (ACK). At this point, the connection is established, and both the client's socket and the server's new socket can be used to send and receive data.
Client-Server Program using Sockets
Here is a complete example of a simple client-server application. The client sends a message to the server, and the server prints it and sends a confirmation back.
Server Code (EchoServer.java
)
This server listens on port 1234. It will handle multiple clients one after another, echoing back whatever message it receives.
import java.net.ServerSocket;
import java.net.Socket;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class EchoServer {
public static void main(String[] args) {
try (ServerSocket serverSocket = new ServerSocket(1234)) {
System.out.println("Server is listening on port 1234...");
// Wait for a client to connect.
try (Socket clientSocket = serverSocket.accept();
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()))) {
System.out.println("Client connected: "
+ clientSocket.getInetAddress());
// Read message from client and echo it back.
String line = in.readLine();
System.out.println("Received: " + line);
out.println("Echo: " + line);
}
} catch (Exception e) {
System.out.println("Server exception: "
+ e.getMessage());
}
}
}
Explanation
Create
ServerSocket
: TheServerSocket
class is used for server-side communication. It acts as a "listener" that waits for clients to connect on a specified port.Wait for Connection: The
serverSocket.accept()
method is a blocking call that pauses the program until a client connects. When a connection is made, it returns aSocket
object for communicating with that specific client.Get I/O Streams: To send and receive data, the program gets an
InputStream
and anOutputStream
from the client'sSocket
. These are wrapped inBufferedReader
andPrintWriter
for easier text manipulation.Communicate: The server reads a line of text from the client, prints it, and then sends a reply back.
Client Code (Echolient.java
)
This client connects to the server, sends a single message ("Hello, Server!"), and prints the server's echoed response.
import java.net.Socket;
import java.io.PrintWriter;
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class EchoClient {
public static void main(String[] args) {
try (Socket socket = new Socket("localhost", 1234);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()))) {
System.out.println("Connected to server.");
// Send a message to the server.
String message = "Hello, Server!";
out.println(message);
System.out.println("Sent: " + message);
// Print the server's response.
System.out.println("Received: " + in.readLine());
} catch (Exception e) {
System.out.println("Client exception: "
+ e.getMessage());
}
}
}
Explanation
Create
Socket
: TheSocket
class is used for client-side communication. Creating aSocket
object with the server's hostname and port implicitly establishes a connection.Get I/O Streams: Just like the server, the client gets input and output streams to communicate.
Communicate: The client sends its message to the server and then waits to read the server's reply.
‘whois’ Client Program
The 'whois' protocol is used to query information about domain names. This program connects to a 'whois' server, sends a domain name provided as a command-line argument, and prints the server's response.
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class WhoisClient {
public static void main(String[] args) {
if (args.length < 1) {
System.out.println("Type Address to lookup");
return;
}
String domainName = args[0];
String server = "whois.internic.net";
int port = 43; // The standard port for whois
try (Socket socket = new Socket(server, port)) {
System.out.println("Connecting to "
+ server + " on port " + port + "...");
// Get input and output streams
OutputStream out = socket.getOutputStream();
InputStream in = socket.getInputStream();
// The whois protocol requires the query to end with a newline
String query = domainName + "\r\n";
byte[] queryBytes = query.getBytes();
// Send the domain name query to the server
out.write(queryBytes);
System.out.println("Sent query for: "
+ domainName);
// Read the response from the server
System.out.println("\n--- Server Response ---");
int c;
while ((c = in.read()) != -1) {
System.out.print((char) c);
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
}
}
}
Compile:
javac WhoisClient.java
Run with a domain name:
java WhoisClient google.com
Roles of DatagramSocket
and DatagramPacket
in UDP
communication.
UDP is a connectionless protocol where data is sent in bundles called datagrams. It is faster than TCP but unreliable, as packets may be lost or arrive out of order.
Java implements UDP using two main classes: DatagramSocket
and DatagramPacket
.
DatagramSocket
A DatagramSocket
is a network socket that acts as the endpoint used to send or receive UDP / datagram packets.
You can create one on a specific port to listen for data or let the system assign an available port for sending.
DatagramSocket()
: Creates a socket on any available port.DatagramSocket(int port)
: Creates a socket that listens on a specific port.
Its key roles are:
Sending Data: It sends a
DatagramPacket
out onto the network. You don't establish a persistent connection; you just "fire and forget" the packet.Receiving Data: It binds to a specific port on the local machine and listens for any incoming
DatagramPacket
s sent to that port from any source.
DatagramPacket
A DatagramPacket
is a container for the data being sent or received. It's the message itself, bundled with its addressing information.
For sending: Create a packet containing the data (as a byte array), the destination IP address, and the port.
DatagramPacket(byte data [ ], int size, InetAddress ipAddress, int port)
For receiving: Create an empty
DatagramPacket
with a byte array buffer. When data arrives, the socket fills the buffer and provides the sender's address and port.DatagramPacket(byte data [ ], int size)