Java Networking / Overview
Course Overview

Java Networking

Master socket programming and HTTP servers in Java. Complete each lesson, pass the exercises, and watch your progress climb to 100%.

What you'll build
Multi-threaded Echo Server
Part 1 · 5 lessons · ServerSocket, threads, streams
HTTP REST Server
Part 2 · 4 lessons · HttpServer, routing, JSON API
Course structure
#LessonExercise typeMarks
1Networking BasicsMCQ10
2Streams & WrappersFill Blanks10
3ServerSocketMCQ10
4Multi-threadingFill Blanks10
5Resource CleanupCode Order10
6HTTP FundamentalsMCQ10
7HttpServer SetupFill Blanks10
8HttpExchangeMCQ10
9Headers & BodyFill Blanks10
10Final ChallengeDebug & MCQ10
How it works

Read each lesson, then complete the exercise at the bottom. Every completed exercise adds 10% to your overall progress. You need to score at least 1 correct answer to unlock the lesson as done.

Lesson 01 · Part 1

Networking Basics

Understand IP addresses, ports, TCP, and why sockets exist — the mental models you need before writing a single line of code.

The Phone Call Analogy

Networking is just two programs talking to each other. Think of it exactly like a phone call:

• The server is like a business with a listed phone number — it waits for calls.
• The client dials in — it initiates the connection.
• Once connected, both sides can talk and listen simultaneously.

IP Address & Port
IP Addresswhich computer Portwhich program on that computer Example: localhost : 8000 ← your own machine, port 8000 10.0.0.5 : 6666 ← another machine, port 6666
PortCommon use
80HTTP (websites)
443HTTPS (secure websites)
8000Development HTTP servers
6666Our custom socket server
TCP vs HTTP
FeatureTCP (Raw Socket)HTTP
LevelLow-level transportBuilt on top of TCP
FormatRaw bytes / textStructured (headers + body)
Java classServerSocketHttpServer
Use caseChat, game serversWeb APIs, browsers
Quick Tip

HTTP doesn't replace TCP — it's built on top of it. Every HTTP request is a TCP connection under the hood. Java's HttpServer abstracts all of that for you.

MCQ Knowledge Check

Q1. What does a port number identify?

AThe physical location of the computer
BThe IP address of the server
CWhich specific program on a computer should receive the data
DThe speed of the network connection

Q2. Which Java class is used to build a raw TCP socket server?

AHttpServer
BServerSocket
CDatagramSocket
DNetworkAdapter

Q3. HTTP is built on top of which protocol?

AUDP
BFTP
CTCP
DSMTP
Lesson 02 · Part 1

Streams & Wrappers

Data flows through sockets as raw bytes. You'll learn the three-layer wrapping pattern that turns those bytes into readable lines of text.

The Wrapper Chain
Raw socket → InputStream (bytes, painful)InputStreamReader (bytes → chars, handles encoding)BufferedReader (chars → full lines, easy!)in.readLine() (returns a complete line of text)
Reading from a Socket
// Step 1: raw bytes from socket
InputStream rawIn = clientSocket.getInputStream();

// Step 2: convert bytes to characters
InputStreamReader charReader = new InputStreamReader(rawIn);

// Step 3: efficient line-by-line reading
BufferedReader in = new BufferedReader(charReader);

// Or all in one line (most common):
BufferedReader in = new BufferedReader(
    new InputStreamReader(clientSocket.getInputStream())
);

String line = in.readLine(); // blocks until a line arrives
Writing — PrintWriter
Writing to a Socket
// true = auto-flush: data sent IMMEDIATELY after println()
PrintWriter out = new PrintWriter(
    clientSocket.getOutputStream(), true
);

out.println("Hello, client!"); // sent right away
Critical — Auto-Flush

Always pass true as the second argument to PrintWriter. Without it, your messages sit in a buffer and the client never receives them until you manually call out.flush() or close the stream.

Memory Trick

Think of the wrappers like Russian dolls — each one adds a capability. InputStream = raw bytes. InputStreamReader = speaks English. BufferedReader = reads full sentences.

Fill in the Blanks Complete the Code

Fill in each blank with the correct class or method name. Case-sensitive.

Q1. Complete the three-layer reading chain:

BufferedReader in = new (   new (     socket.()   ) );

Q2. Create a PrintWriter with auto-flush enabled:

PrintWriter out = new PrintWriter(socket.getOutputStream(), );

Q3. Which method reads a full line from a BufferedReader?

String line = in.();
Lesson 03 · Part 1

ServerSocket — The Listener

ServerSocket is your server's front door. Learn how to create it, bind it to a port, and accept incoming client connections.

Connection Lifecycle
SERVER CLIENT │ │ │ 1. new ServerSocket(6666) │ │ 2. serverSocket.accept() ←─wait─ │ │ 3. new Socket("host", 6666) │ ◄─────── connection established ───────────── │ 4. Got a Socket object │ │ 5. Streams open → communicate │ │ 6. Close socket │
Creating a Server
// Bind to port 6666, IOException must be handled
ServerSocket serverSocket = new ServerSocket(6666);

// Block until a client connects — returns a live Socket
Socket clientSocket = serverSocket.accept();

// Loop to accept MANY clients (one at a time, sequentially)
while (true) {
    Socket client = serverSocket.accept(); // waits here
    // handle client...
}
Remember

new ServerSocket(port) throws IOException. Always wrap it in a try-catch or declare throws IOException on the method. The port must be between 1 and 65535, and not already in use.

What is Backlog?

The backlog (second optional argument) is how many pending connections can queue up before the OS starts rejecting them. new ServerSocket(6666) uses the OS default. For the exam, always use 0 with HttpServer's factory method.

MCQ ServerSocket Quiz

Q1. What does serverSocket.accept() return?

AA ServerSocket representing the server
BA Socket representing the connected client
CA boolean indicating connection success
DAn InputStream from the client

Q2. What exception must you handle when creating a ServerSocket?

ARuntimeException
BSocketException
CIOException
DNetworkException

Q3. What does accept() do while waiting for a client?

AReturns null immediately
BThrows a TimeoutException
CBlocks (pauses) the current thread
DSpawns a new thread automatically
Lesson 04 · Part 1

Multi-threading

Handle multiple clients simultaneously using threads and the Runnable pattern — the heart of a real server.

The Problem with Single-Threaded
❌ Single-threaded (BAD): Client A connects → handle(A) → Client B waits... and waits... and waits ✅ Multi-threaded (GOOD): Client A connects → new Thread → handle(A) ─┐ Client B connects → new Thread → handle(B) ─┤ all run at the same time Client C connects → new Thread → handle(C) ─┘
Multi-threaded accept loop
while (true) {
    Socket client = serverSocket.accept();         // wait
    ClientHandler handler = new ClientHandler(client); // create
    Thread thread = new Thread(handler);           // wrap
    thread.start();                                // launch (non-blocking!)
    // loop IMMEDIATELY back to accept() for next client
}
The ClientHandler Pattern
ClientHandler inner class
private static class ClientHandler implements Runnable {

    private final Socket clientSocket;

    public ClientHandler(Socket socket) {
        this.clientSocket = socket; // store the connection
    }

    @Override
    public void run() {
        // This runs in a separate thread
        // Set up streams, echo loop, cleanup...
    }
}
Why private static?

static means the inner class doesn't hold a reference to the outer class. This prevents accidental memory leaks — the handler only needs the Socket, nothing else from the outer SocketServerExam class.

The Echo Loop
Echo loop inside run()
String inputLine;
while ((inputLine = in.readLine()) != null) {
    // readLine() returns null when client disconnects
    System.out.println("Received: " + inputLine);
    out.println("Echo: " + inputLine);
}
Fill in the Blanks Thread & Handler Exercise

Q1. Complete the multi-threaded accept loop:

while () {   Socket client = serverSocket.accept();   ClientHandler h = new ClientHandler(client);   Thread t = new (h);   t.(); }

Q2. What interface does ClientHandler implement?

private static class ClientHandler implements { ... }

Q3. What value does readLine() return when the client disconnects?

while ((line = in.readLine()) != ) { ... }
Lesson 05 · Part 1

Resource Cleanup

Network resources must always be closed — even when exceptions occur. Master the finally block and try-with-resources patterns.

The finally Pattern
finally block cleanup
// Declare BEFORE try so finally can see them
BufferedReader in = null;
PrintWriter out = null;

try {
    in  = new BufferedReader(...);
    out = new PrintWriter(..., true);
    // communicate...
} catch (IOException e) {
    System.err.println("Error: " + e.getMessage());
} finally {
    // ALWAYS runs — even after an exception
    try {
        if (clientSocket != null) clientSocket.close();
        if (in  != null) in.close();
        if (out != null) out.close();
    } catch (IOException e) { e.printStackTrace(); }
}
try-with-resources (Cleaner)
Auto-close with try-with-resources
// Resources in () are auto-closed when block exits
try (Socket client = serverSocket.accept();
     BufferedReader in = new BufferedReader(
         new InputStreamReader(client.getInputStream()));
     PrintWriter out = new PrintWriter(
         client.getOutputStream(), true)) {

    String line;
    while ((line = in.readLine()) != null) {
        out.println("Echo: " + line);
    }
} // client, in, out all closed automatically here
Key Rule

Declare BufferedReader in = null and PrintWriter out = null before the try block. If you declare them inside the try, the finally block can't see them — Java scoping rule.

Code Order Arrange the Cleanup Steps

Click the code chips in the correct order to build the finally cleanup block. Click a placed chip to remove it.

} finally { try { ___ ___ ___ } catch(IOException e) { e.printStackTrace(); } }

if (out != null) out.close();
if (clientSocket != null) clientSocket.close();
System.out.println(line);
if (in != null) in.close();
serverSocket.accept();
Your answer (click to remove):
Lesson 06 · Part 2

HTTP Fundamentals

Learn the structure of HTTP requests and responses, common methods, and status codes — the vocabulary of the web.

Request Structure
POST /data HTTP/1.1 ← Method + Path + Version Host: localhost:8000 ← Headers User-Agent: curl/7.88 Content-Type: application/json ← blank line separates headers from body { "name": "Alice" } ← Body (POST/PUT only)
HTTP Methods
MethodPurposeHas body?
GETRetrieve data (load a page)No
POSTSend data to serverYes
PUTUpdate existing dataYes
DELETERemove dataNo
Status Codes
CodeMeaningWhen
200OKRequest succeeded
201CreatedResource was created
400Bad RequestClient sent bad data
404Not FoundPath doesn't exist
405Method Not AllowedWrong verb (e.g., GET on POST route)
500Internal Server ErrorSomething crashed on the server
Memory Trick — Status Code Groups

2xx = Success   3xx = Redirect   4xx = Client's fault   5xx = Server's fault

MCQ HTTP Quiz

Q1. Your server's /data route only accepts POST. A client sends a GET request. What status code should you return?

A404 Not Found
B400 Bad Request
C405 Method Not Allowed
D500 Internal Server Error

Q2. Which HTTP method is used for sending a new data payload to the server (like submitting a form)?

AGET
BPOST
CDELETE
DHEAD

Q3. What separates the headers from the body in an HTTP request?

AA semicolon ;
BA blank line
CThe word "BODY"
DThree dashes ---
Lesson 07 · Part 2

HttpServer Setup

Create and configure Java's built-in HTTP server — factory method, routing with contexts, and executors.

Creating the Server
HttpServer creation
// Factory method — NOT "new HttpServer(...)"
HttpServer server = HttpServer.create(
    new InetSocketAddress(8000), // bind to port 8000
    0                              // backlog = 0 (OS default)
);
Routing with Contexts
Adding routes
server.createContext("/",     new RootHandler());
server.createContext("/data", new DataHandler());

server.setExecutor(null);  // default single-threaded
server.start();             // begin accepting connections
Executor Options
setExecutor(…)BehaviourUse case
nullSingle-threaded, one request at a timeExams, demos
Executors.newFixedThreadPool(10)Max 10 concurrent requestsProduction
Executors.newCachedThreadPool()Dynamic — scales up/downVariable load
Factory Method Pattern

HttpServer.create() is a factory method — you call it on the class itself, not with new. This is common in Java when the actual implementation returned may vary. You always get an HttpServer back regardless.

Fill in the Blanks Server Setup Exercise

Q1. Create an HttpServer on port 8000:

HttpServer server = .(   new InetSocketAddress(), 0 );

Q2. Register routes and start:

server.("/", new RootHandler()); server.setExecutor(); server.();
Lesson 08 · Part 2

HttpExchange

The HttpExchange object is your window into every request — and your tool to write every response. Master its API.

The HttpExchange API
HttpExchange ├── getRequestMethod() → "GET", "POST", "DELETE"... ├── getRequestURI() → the path requested ├── getRequestHeaders() → Headers (read-only) ├── getRequestBody() → InputStream (read the body) ├── getResponseHeaders() → Headers (set your response headers) ├── sendResponseHeaders() → status code + body length └── getResponseBody() → OutputStream (write your response)
Sending a Response — 3 Steps
The response pattern
String response = "<html><body><h1>Hello</h1></body></html>";

// Step 1: Set response headers (optional, do this FIRST)
exchange.getResponseHeaders().set("Content-Type", "text/html");

// Step 2: Send status code + byte count
exchange.sendResponseHeaders(200, response.getBytes().length);

// Step 3: Write body and close
try (OutputStream os = exchange.getResponseBody()) {
    os.write(response.getBytes());
} // auto-closed here
Critical Rules

1. Always call sendResponseHeaders() before writing the body.
2. Always close() the OutputStream — the client waits forever without it.
3. Use -1 as content length when there's no body (e.g., 405 responses).

MCQ HttpExchange Quiz

Q1. What content length should you pass to sendResponseHeaders() when there is no response body?

A0
B-1
Cnull
DInteger.MAX_VALUE

Q2. Which method gives you an OutputStream to write the HTTP response body?

Aexchange.getRequestBody()
Bexchange.getOutputStream()
Cexchange.getResponseBody()
Dexchange.sendResponse()

Q3. In what order must these three steps happen?

AWrite body → sendResponseHeaders() → close stream
BsendResponseHeaders() → write body → close stream
Cclose stream → sendResponseHeaders() → write body
DAny order works
Lesson 09 · Part 2

Headers & Request Body

Read what the client sends — headers for metadata, the body for POST data — and respond with the right Content-Type.

Reading Request Headers
Accessing headers
// Get the Headers map
Headers requestHeaders = exchange.getRequestHeaders();

// Read one header (case-insensitive key)
String userAgent = requestHeaders.getFirst("User-Agent");
System.out.println("User-Agent: " + userAgent);

// Headers is like Map<String, List<String>>
// getFirst() returns the first value for that key
Reading the Request Body
Reading POST body
// Get the input stream
InputStream inputStream = exchange.getRequestBody();

// Read ALL bytes at once (Java 9+)
byte[] requestBody = inputStream.readAllBytes();

// Convert to String if text
String bodyText = new String(requestBody);
Setting Response Content-Type
JSON response with Content-Type
String json = "{ \"status\": \"success\" }";

// IMPORTANT: set Content-Type BEFORE sendResponseHeaders
exchange.getResponseHeaders().set(
    "Content-Type",
    "application/json"
);

exchange.sendResponseHeaders(200, json.getBytes().length);

try (OutputStream os = exchange.getResponseBody()) {
    os.write(json.getBytes());
}
Always Read the Body

Even if you don't use the POST body, call getRequestBody().readAllBytes(). Some HTTP clients wait for the server to consume the request before reading the response — not reading it can cause the client to hang.

Fill in the Blanks Headers & Body Exercise

Q1. Read the User-Agent request header:

Headers h = exchange.(); String ua = h.("User-Agent");

Q2. Read all bytes from the request body:

InputStream is = exchange.(); byte[] body = is.();

Q3. Set the response Content-Type to JSON:

exchange.getResponseHeaders().("Content-Type", );
Lesson 10 · Final Challenge

Final Challenge

Prove you've mastered everything — spot the bugs, fill the blanks, and answer the comprehensive MCQ to complete the course.

Bug Hunt — Spot the Mistakes

The code below has 3 bugs. Find them before doing the MCQ!

Buggy Code — Find 3 Errors
// Bug Hunt Exercise

// Bug 1 — PrintWriter
PrintWriter out = new PrintWriter(socket.getOutputStream()); // ← ?

// Bug 2 — sending a 405 with no body
exchange.sendResponseHeaders(405, 0); // ← ?

// Bug 3 — method check then continue without return
if (!method.equals("POST")) {
    exchange.sendResponseHeaders(405, -1);
    // ← missing something here!
}
String json = "{ \"status\": \"success\" }";
exchange.sendResponseHeaders(200, json.length()); // ← headers already sent!

Bug 1: What is wrong with new PrintWriter(socket.getOutputStream())?

AgetOutputStream() is the wrong method
BMissing second argument true for auto-flush
CPrintWriter doesn't accept an OutputStream
DPrintWriter should be BufferedWriter

Bug 2: Why is sendResponseHeaders(405, 0) wrong for a no-body response?

A405 is not a valid HTTP status code
BThe method should be sendHeaders() not sendResponseHeaders()
C0 means "send a 0-byte body", causing the client to hang. Use -1.
D0 and -1 are equivalent, there's no bug

Bug 3: What is the missing statement after sending the 405?

Abreak;
Breturn;
Ccontinue;
Dthrow new IOException();

Q4 (Comprehensive): Which of the following correctly describes the three-step response pattern in HttpServer?

AWrite body bytes → call sendResponseHeaders() → close stream
BSet Content-Type → close stream → call sendResponseHeaders()
CSet response headers → sendResponseHeaders(status, length) → write body → close stream
DsendResponseHeaders() → set headers → write body → close

Course Complete!

You've mastered Java Socket Servers and HTTP Servers — from raw TCP streams to routing, headers, and JSON responses. You're ready for the exam.

10
Lessons Completed
100%
Overall Progress
2
Servers Mastered