Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Java Client–Server Networking

Notes covering Java TCP/IP, UDP, traditional blocking I/O, multithreading, NIO channels, polling and event-driven selectors.

1. TCP Client–Server Basics

  • TCP provides reliable, ordered and two-way communication.
  • ServerSocket listens for connections on a port.
  • Socket represents a connection between one client and server.
  • accept() waits for a client and returns its Socket.
  • getInputStream() receives data.
  • getOutputStream() sends data.
  • readLine() waits for a complete newline-terminated message.
  • PrintWriter(..., true) automatically flushes data with println().
Client → Request → Server
Client ← Response ← Server

2. Single-Client Blocking Server

When accept() is called only once, the server accepts only one client.

Both methods are blocking:

serverSocket.accept(); // Waits for a client
input.readLine();      // Waits for client data

If the connected client remains inactive, the server cannot process another client.

3. Accept Loop and Socket Timeout

Placing accept() inside a loop lets the server accept clients sequentially:

Handle client A completely
→ Handle client B
→ Handle client C

It still does not handle them simultaneously.

socket.setSoTimeout(20_000);
  • Sets a read-inactivity timeout of 20 seconds.
  • Causes a blocked read to throw SocketTimeoutException.
  • It prevents an inactive client from blocking forever.
  • It does not create concurrency.

4. Multithreaded Server

The main thread accepts connections, while worker threads handle clients.

ExecutorService executor =
        Executors.newFixedThreadPool(20);

executor.submit(() -> handleClientRequest(socket));
  • Up to 20 clients can be handled simultaneously.
  • Extra tasks wait in the executor queue.
  • One blocked client affects only its worker thread.
  • Each worker may still block inside readLine().
  • Many idle connections can consume significant thread and memory resources.

5. Java NIO Channels and Buffers

NIO uses channels and buffers instead of streams.

Traditional I/O NIO
ServerSocket ServerSocketChannel
Socket SocketChannel
Input/output streams ByteBuffer

Important buffer operations:

buffer.flip();  // Write mode → read mode
buffer.clear(); // Prepare for new data

clear() resets the position and limit; it does not necessarily erase the old bytes.

Channel read results:

  • > 0: Bytes were received.
  • 0: No data is currently available.
  • -1: The remote client disconnected.

Using channels alone does not make code non-blocking.

6. Non-Blocking Polling Server

Enable non-blocking mode:

serverChannel.configureBlocking(false);
clientChannel.configureBlocking(false);

In this mode:

  • accept() returns null if no client is waiting.
  • read() returns 0 if no data is available.
  • One thread can repeatedly check multiple clients.
Is a new client connecting?
Does client A have data?
Does client B have data?
Repeat...

This is called polling. It supports multiple clients but wastes CPU by continuously checking inactive channels.

7. Event-Driven Server with Selector

A Selector monitors multiple non-blocking channels and reports only the channels that are ready.

serverChannel.register(selector, SelectionKey.OP_ACCEPT);
clientChannel.register(selector, SelectionKey.OP_READ);

Main operations:

Operation Meaning
OP_ACCEPT A client is ready to be accepted
OP_CONNECT A connection can finish
OP_READ Data is ready to read
OP_WRITE Output can be written
selector.select();

select() efficiently blocks until any registered event occurs.

Processing flow:

Selector wakes
→ Get selected keys
→ Accept or read
→ Remove processed key
→ Wait again

Always remove processed selected keys:

iterator.remove();

SelectionKey connects a channel, selector and registered operations.

key.channel(); // Registered channel
key.cancel();  // Cancel registration

A selector provides concurrency with one event-loop thread, not parallel execution.

Avoid blocking the event-loop thread with slow database calls, file operations, external HTTP calls or CPU-intensive work. This event-loop model is used by Netty and Spring WebFlux.

8. TCP Limitations to Remember

TCP is a byte stream and does not preserve message boundaries.

One read() may contain:

  • Part of one message
  • One complete message
  • Multiple messages

Applications need message framing, such as newline-delimited or length-prefixed messages.

Non-blocking writes can also be partial. Large pending responses should be stored and completed using OP_WRITE.

9. UDP and DatagramChannel

UDP is connectionless and does not guarantee:

  • Delivery
  • Ordering
  • Duplicate protection

It is useful when speed matters more than perfect delivery, such as audio/video streaming, gaming and real-time communication.

NIO uses:

DatagramChannel

Important methods:

channel.receive(buffer);        // Receive a datagram
channel.send(buffer, address);  // Send to a client address

Unlike TCP, UDP does not use accept() and does not create a separate connection for every client.

10. UDP Selector and Thread Pool

The UDP server registers one DatagramChannel for read events:

datagramChannel.register(
        selector,
        SelectionKey.OP_READ
);

The main event-loop thread:

  1. Receives the client’s file request.
  2. Reads the client’s address.
  3. Submits audio streaming to the executor.
executor.submit(() ->
    sendDataToClient(file, clientAddress, datagramChannel)
);

Worker threads read the audio file using FileChannel and send it in UDP packets.

Important distinction:

  • Selector provides event-driven channel monitoring.
  • ExecutorService makes audio streaming multithreaded.
  • A selector alone does not create multiple threads.

Final Comparison

Approach Model Main limitation
Single blocking server One client only one client is handled
Accept loop + timeout Sequential clients No simultaneous handling
Thread pool Worker per active client Many blocked threads
Non-blocking polling One thread, many clients Wastes CPU
Selector Event-driven single thread More complex state handling
Selector + thread pool Event loop plus workers Requires careful coordination

Key Takeaway

Blocking I/O is simple and suitable for smaller systems. NIO selectors allow one thread to manage many connections efficiently. Thread pools should be used for blocking or long-running work so that the event-loop thread remains responsive.

About

In this repository, I explored networking concepts covering TCP/UDP client-server communication, ServerSocket, Socket, ServerSocketChannel, blocking and non-blocking NIO, Selector-based event loops, multithreaded servers, and UDP file streaming.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages