In this section, we will delve into the ServerSocket class in Java, which is used to create server applications that can accept client connections. This is a crucial concept for building networked applications where a server needs to handle multiple client requests.

Key Concepts

  1. ServerSocket Class: A class in Java that provides a mechanism for the server to listen for client requests on a specific port.
  2. Port: A numerical identifier in the range 0-65535 that is used to distinguish different services on a server.
  3. Socket: An endpoint for communication between two machines.

Creating a ServerSocket

To create a ServerSocket, you need to specify a port number on which the server will listen for incoming connections. Here is a basic example:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class SimpleServer {
    public static void main(String[] args) {
        int port = 1234; // Port number on which the server will listen
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);
            while (true) {
                Socket socket = serverSocket.accept(); // Wait for a client to connect
                System.out.println("New client connected");
                // Handle the client connection in a separate thread or method
            }
        } catch (IOException e) {
            System.out.println("Server exception: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Explanation

  • ServerSocket serverSocket = new ServerSocket(port): Creates a ServerSocket that listens on the specified port.
  • serverSocket.accept(): Waits for a client to connect and returns a Socket object representing the client connection.
  • try-with-resources: Ensures that the ServerSocket is closed automatically when the try block exits.

Handling Client Connections

Once a client connects, you can handle the connection using the Socket object returned by the accept() method. Here is an example of how to read from and write to the client:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class EchoServer {
    public static void main(String[] args) {
        int port = 1234;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("New client connected");

                // Create input and output streams for the socket
                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter output = new PrintWriter(socket.getOutputStream(), true);

                String clientMessage;
                while ((clientMessage = input.readLine()) != null) {
                    System.out.println("Received: " + clientMessage);
                    output.println("Echo: " + clientMessage); // Echo the message back to the client
                }
            }
        } catch (IOException e) {
            System.out.println("Server exception: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Explanation

  • BufferedReader input: Reads text from the client's input stream.
  • PrintWriter output: Sends text to the client's output stream.
  • input.readLine(): Reads a line of text from the client.
  • output.println(): Sends a line of text to the client.

Practical Exercise

Task

Create a simple server application that listens on port 5678 and responds with the current date and time whenever a client connects and sends a message.

Solution

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DateTimeServer {
    public static void main(String[] args) {
        int port = 5678;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("New client connected");

                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                PrintWriter output = new PrintWriter(socket.getOutputStream(), true);

                String clientMessage;
                while ((clientMessage = input.readLine()) != null) {
                    System.out.println("Received: " + clientMessage);
                    if (clientMessage.equalsIgnoreCase("time")) {
                        String currentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
                        output.println("Current Date and Time: " + currentTime);
                    } else {
                        output.println("Unknown command");
                    }
                }
            }
        } catch (IOException e) {
            System.out.println("Server exception: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

Explanation

  • LocalDateTime.now(): Gets the current date and time.
  • DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"): Formats the date and time in a readable format.
  • clientMessage.equalsIgnoreCase("time"): Checks if the client sent the "time" command.

Common Mistakes and Tips

  • Port Already in Use: Ensure the port you are trying to use is not already in use by another application.
  • Firewall Issues: Make sure your firewall settings allow traffic on the port you are using.
  • Resource Management: Always close the ServerSocket and Socket objects to free up resources.

Conclusion

In this section, we covered the basics of using the ServerSocket class to create a simple server application in Java. We learned how to accept client connections, read from and write to clients, and handle multiple client requests. This knowledge is fundamental for building more complex networked applications. In the next section, we will explore DatagramSocket and DatagramPacket for UDP communication.

Java Programming Course

Module 1: Introduction to Java

Module 2: Control Flow

Module 3: Object-Oriented Programming

Module 4: Advanced Object-Oriented Programming

Module 5: Data Structures and Collections

Module 6: Exception Handling

Module 7: File I/O

Module 8: Multithreading and Concurrency

Module 9: Networking

Module 10: Advanced Topics

Module 11: Java Frameworks and Libraries

Module 12: Building Real-World Applications

© Copyright 2024. All rights reserved