Core Java

Java ServerSocket Simple HTTP Server Example

An HTTP server is responsible for serving resources to a requesting client. While Java offers several production-grade web servers, understanding the inner workings of an HTTP server can be achieved by building one using the ServerSocket class. Let’s delve into understanding how a Java ServerSocket can be used to build a simple HTTP server, allowing us to handle client requests and serve responses efficiently.

1. What is a Web Server?

A web server is a software or hardware that processes HTTP requests and serves web pages or files to clients, typically web browsers. It acts as an intermediary between users and web applications.

1.1 Functions of a Web Server

A web server performs the following tasks:

  • Receives HTTP requests from clients (such as browsers).
  • Processes the requests and retrieves the requested resource.
  • Sends the response back to the client, typically an HTML page, JSON data, or an image.
  • Handles dynamic content by interacting with databases and application logic.

1.2 Types of Web Servers

There are several types of web servers:

  • Apache HTTP Server – One of the most widely used open-source web servers.
  • Nginx – Known for high performance and scalability.
  • Microsoft IIS – A web server developed by Microsoft for Windows environments.
  • LiteSpeed – A lightweight, high-performance alternative to Apache.
  • Tomcat – A Java-based web server used for running Java Servlets and JSP applications.

1.3 Understanding ServerSocket

A web server listens for HTTP requests on a specified port. When a request is received, the server processes it and sends an appropriate HTTP response. Java’s ServerSocket class provides a way to accept client connections and handle them using sockets.

1.3.1 Working of ServerSocket

When a client sends a request, the accept() method of the ServerSocket blocks until a connection is established, returning a Socket object to handle communication. The server can then send and receive data using input and output streams. Typically used in web servers, chat applications, and distributed systems, ServerSocket enables efficient client-server communication by continuously listening for new connections.

2. Initializing a ServerSocket instance

Let’s start by creating a simple server that listens on port 8080 and responds with a plain text message.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class SimpleHttpServer {
    public static void main(String[] args) {
        int port = 8080;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is listening on port " + port);
            while (true) {
                Socket clientSocket = serverSocket.accept();
                handleRequest(clientSocket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    private static void handleRequest(Socket clientSocket) throws IOException {
        String httpResponse = "HTTP/1.1 200 OK\r\n"
                + "Content-Type: text/html; charset=UTF-8\r\n"
                + "Connection: close\r\n\r\n"
                + "<!DOCTYPE html>"
                + "<html lang=\"en\">"
                + "<head><title>Simple HTTP Server</title></head>"
                + "<body><h1>Hello, World!</h1></body>"
                + "</html>";
 
        OutputStream outputStream = clientSocket.getOutputStream();
        outputStream.write(httpResponse.getBytes());
        outputStream.flush();
        clientSocket.close();
    }
}

2.1 Code Explanation and Output

This Java program implements a simple HTTP server that listens on port 8080 and responds with a basic HTML webpage. The main method initializes a ServerSocket and continuously waits for incoming client connections. When a client connects, the handleRequest method is called, which constructs an HTTP response with headers (HTTP/1.1 200 OK, Content-Type: text/html; charset=UTF-8, and Connection: close) followed by a simple HTML document containing a <title> in the <head> and an <h1> heading in the <body>. The response is sent through the output stream, and the connection is closed afterward, ensuring proper request handling.

We will use the curl command to test the output:

Once the curl command is triggered the following output will be returned:

1
2
3
4
5
6
7
8
9
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Connection: close
 
<!DOCTYPE html>
<html lang="en">
<head><title>Simple HTTP Server</title></head>
<body><h1>Hello, World!</h1></body>
</html>

3. Managing Input and Output Operations

The server reads the client’s request and then responds appropriately. Here’s an improved version that reads the HTTP request.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
 
public class HttpRequestHandler {
    public static void main(String[] args) {
        int port = 8080;
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            System.out.println("Server is running on port " + port);
            while (true) {
                Socket clientSocket = serverSocket.accept();
                handleRequest(clientSocket);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    private static void handleRequest(Socket clientSocket) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String line;
        while (!(line = reader.readLine()).isBlank()) {
            System.out.println(line);
        }
         
        String responseBody = "Welcome to our simple server!";
        String date = getServerTime();
        String serverName = "SimpleJavaHTTPServer/1.0";
        String contentType = "text/plain; charset=UTF-8";
        String contentLength = String.valueOf(responseBody.length());
         
        String httpResponse = "HTTP/1.1 200 OK\r\n"
                + "Date: " + date + "\r\n"
                + "Server: " + serverName + "\r\n"
                + "Content-Type: " + contentType + "\r\n"
                + "Content-Length: " + contentLength + "\r\n"
                + "Connection: close\r\n\r\n"
                + responseBody;
         
        OutputStream outputStream = clientSocket.getOutputStream();
        outputStream.write(httpResponse.getBytes());
        outputStream.flush();
        clientSocket.close();
    }
     
    private static String getServerTime() {
        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        return dateFormat.format(new Date());
    }
}

3.1 Code Explanation and Output

This Java program implements a basic HTTP server that listens on port 8080 and responds to incoming client requests. The main method initializes a ServerSocket and continuously accepts connections. When a client connects, the handleRequest method processes the request by reading incoming data and printing it to the console. The server then constructs an HTTP response with standard headers like Date, Server, Content-Type, and Content-Length to ensure compliance with HTTP standards. The response body contains a simple text message, Welcome to our simple server!. The getServerTime method generates the current server time in GMT format for the Date header. Finally, the response is sent to the client, and the connection is closed.

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Date: Fri, 07 Mar 2025 12:00:00 GMT
Server: SimpleJavaHTTPServer/1.0
Content-Type: text/plain; charset=UTF-8
Content-Length: 27
Connection: close
 
Welcome to our simple server!

4. Concurrent Multi-threaded Server

To handle multiple clients simultaneously, we use multithreading by assigning each client request to a new thread.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
import java.io.*;
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
 
public class MultiThreadedHttpServer {
  public static void main(String[] args) {
    int port = 8080;
    ExecutorService threadPool = Executors.newFixedThreadPool(
        10); // Using a thread pool to manage threads efficiently
    try (ServerSocket serverSocket = new ServerSocket(port)) {
      System.out.println("Multi-threaded Server running on port " + port);
      while (true) {
        Socket clientSocket = serverSocket.accept();
        threadPool.execute(new ClientHandler(clientSocket));
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}
 
class ClientHandler implements Runnable {
  private Socket clientSocket;
 
  public ClientHandler(Socket socket) {
    this.clientSocket = socket;
  }
 
  private static String getServerTime() {
    SimpleDateFormat dateFormat =
        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    return dateFormat.format(new Date());
  }
 
  @Override
  public void run() {
    try {
      BufferedReader reader = new BufferedReader(
          new InputStreamReader(clientSocket.getInputStream()));
      String line;
      while (!(line = reader.readLine()).isBlank()) {
        System.out.println(line);
      }
 
      String responseBody = "Hello from a multithreaded server!";
      String date = getServerTime();
      String serverName = "SimpleJavaHTTPServer/1.1";
      String contentType = "text/plain; charset=UTF-8";
      String contentLength = String.valueOf(responseBody.length());
 
      String httpResponse = "HTTP/1.1 200 OK\r\n"
          + "Date: " + date + "\r\n"
          + "Server: " + serverName + "\r\n"
          + "Content-Type: " + contentType + "\r\n"
          + "Content-Length: " + contentLength + "\r\n"
          + "Connection: close\r\n\r\n" + responseBody;
 
      OutputStream outputStream = clientSocket.getOutputStream();
      outputStream.write(httpResponse.getBytes());
      outputStream.flush();
      clientSocket.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

4.1 Code Explanation and Output

This Java program implements a multi-threaded HTTP server that listens on port 8080 and efficiently handles multiple client requests using a thread pool. The main method initializes a ServerSocket and uses an ExecutorService with a fixed thread pool of 10 threads to prevent resource depletion. Each client request is accepted and processed by a ClientHandler, which reads incoming HTTP data and logs it to the console. The server then responds with a basic HTTP response containing “Hello from a multithreaded server!”. Using a thread pool ensures efficient resource management, preventing excessive thread creation and improving server stability.

1
2
3
4
5
6
7
8
HTTP/1.1 200 OK
Date: Fri, 07 Mar 2025 1:00:00 GMT
Server: SimpleJavaHTTPServer/1.1
Content-Type: text/plain; charset=UTF-8
Content-Length: 33
Connection: close
 
Hello from a multithreaded server!

The client will see the following output in the browser, while the server-side output will be:

1
Multi-threaded Server running on port 8080

5. Conclusion

We have successfully created a simple HTTP server using Java’s ServerSocket. We started with a basic implementation and improved it by handling request input and making it multithreaded for better performance. This server can serve as the foundation for building a lightweight HTTP-based service or learning about networking in Java.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button