By WebNest Studio Engineering Team
Advanced Java Tutorial
Networking Basics: Socket, ServerSocket, and URL
Java was built for the internet era, and the java.net package has provided TCP/IP networking support since the very first release. Two classes handle raw socket-based communication — Socket for the client side and ServerSocket for the server side — while URL and URLConnection provide a higher-level way to work with web resources without managing sockets directly.
Understanding both layers matters: sockets are the foundation that protocols like HTTP are built on top of, and most real applications use the higher-level URL classes (or a proper HTTP client library) rather than raw sockets. Advanced Java developers should be comfortable with both.
Why it matters
Every call your back end makes, to a database, a payment gateway or another service, travels over a socket to a host and a port. Frameworks hide the plumbing, but the vocabulary of connections, ports, blocking reads and timeouts is what you need to read a stack trace or a firewall rule when something stops responding.
Socket and ServerSocket
A ServerSocket binds to a port and listens for incoming TCP connections. Calling accept() blocks the current thread until a client connects, then returns a Socket object representing that specific connection. A client creates its own Socket by specifying the server's host and port; once connected, both sides read and write through the socket's input and output streams, exactly like reading and writing a file.
ServerSocket(port)— opens a listening socket on the given port.serverSocket.accept()— blocks until a client connects, then returns a connectedSocket.new Socket(host, port)— the client-side call that initiates a TCP connection.- Both sides use
getInputStream()/getOutputStream()to exchange data.
URL and URLConnection
The URL class parses and represents a Uniform Resource Locator — it can break a web address down into its protocol, host, port, path, and query string without making any network call at all. URLConnection (obtained via url.openConnection()) is what actually performs network I/O: it opens a connection to the resource and lets you read its content as a stream, inspect response headers, or send data. This is the mechanism behind simple HTTP downloads in older and simpler Java code, though modern code typically prefers the more capable java.net.http.HttpClient introduced in Java 11.
Blocking Behavior and Real Applications
Both accept() and stream reads are blocking calls by default — they pause the calling thread until data or a connection arrives. That is why simple socket servers usually accept connections in a loop, often handing each accepted socket off to its own thread (or a thread pool) so one slow client cannot stall every other client. Production servers rarely write raw socket loops like this by hand; they use frameworks (Netty, Spring's embedded servers, and so on) that solve these concurrency and buffering problems for you — but the concepts underneath are exactly Socket, ServerSocket, and the read/write stream model shown here.
Examples
A minimal client-server exchange using Socket and ServerSocket
import java.io.*;
import java.net.*;
public class SocketDemo {
public static void main(String[] args) throws Exception {
// Server: accept one connection on its own thread
Thread server = new Thread(() -> {
try (ServerSocket serverSocket = new ServerSocket(5000)) {
Socket client = serverSocket.accept(); // blocks until a client connects
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream(), true);
String received = in.readLine();
out.println("Server received: " + received);
client.close();
} catch (IOException e) {
e.printStackTrace();
}
});
server.start();
Thread.sleep(200); // give the server a moment to start listening
// Client: connect, send a line, read the reply
try (Socket socket = new Socket("localhost", 5000)) {
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out.println("Hello from client");
System.out.println(in.readLine());
}
server.join();
}
}
Server received: Hello from client
Parsing a resource address with URL (no network call required)
import java.net.URL;
public class UrlDemo {
public static void main(String[] args) throws Exception {
URL url = new URL("https://api.example.com:8443/v1/data?id=42");
System.out.println("Protocol: " + url.getProtocol());
System.out.println("Host: " + url.getHost());
System.out.println("Port: " + url.getPort());
System.out.println("Path: " + url.getPath());
System.out.println("Query: " + url.getQuery());
}
}
Protocol: https
Host: api.example.com
Port: 8443
Path: /v1/data
Query: id=42
Common Mistakes
- Forgetting that ServerSocket.accept() blocks — calling it on the main thread of a GUI or single-threaded server freezes everything else until a client connects.
- Not closing sockets and streams (or not using try-with-resources), which leaks file descriptors and eventually exhausts the OS connection limit.
- Assuming a single ServerSocket automatically handles multiple simultaneous clients — you must accept in a loop and typically dispatch each connection to its own thread.
- Using raw URLConnection for serious HTTP work instead of java.net.http.HttpClient, which offers timeouts, redirects, and async support out of the box.
Exercise
Parse two addresses with java.net.URI, which needs no network access. For the first, print the scheme, the path and the fragment. For the second, which names no port, print what getPort() returns.
Expected output: https, /products/42, reviews, -1 (one per line)
import java.net.URI;
public class ParseAddress {
public static void main(String[] args) {
URI full = URI.create("https://shop.example.com:8443/products/42?ref=home#reviews");
URI plain = URI.create("http://example.com/about");
// TODO: print the scheme, the path and the fragment of "full"
// TODO: print the port of "plain"
}
}
Show hints
- The getters are
getScheme(),getPath()andgetFragment(). - When the address has no explicit port,
getPort()returns-1; the client then uses the default for the scheme.
Show solution
import java.net.URI;
public class ParseAddress {
public static void main(String[] args) {
URI full = URI.create("https://shop.example.com:8443/products/42?ref=home#reviews");
URI plain = URI.create("http://example.com/about");
System.out.println(full.getScheme()); // https
System.out.println(full.getPath()); // /products/42
System.out.println(full.getFragment()); // reviews
System.out.println(plain.getPort()); // -1
}
}
Quick quiz
1. What identifies one end of a network connection?
- A. A file name
- B. An IP address together with a port number
- C. A class name
- D. A thread id
Show answer
B. The address finds the machine, and the port finds the program on it.
2. What does ServerSocket.accept() return?
- A. A Socket connected to the client that just connected
- B. A boolean
- C. The port number
- D. An InputStream
Show answer
A. The server then reads and writes through that socket's streams.
3. Why does a simple server handle each client on a separate thread?
- A. Sockets cannot be reused
- B. Threads make the network faster
- C. The compiler requires it
- D. Reading from a socket blocks, so one slow client would otherwise hold up all the others
Show answer
D. Thread pools or non-blocking I/O are used when there are many clients.
Interview questions
What is the difference between Socket and ServerSocket?
Show answer
ServerSocket is used by a server: it binds to a port and waits, and each call to accept() returns a new Socket for one client. Socket is one end of an established TCP connection: a client creates one by giving the server's host and port. Both sides then exchange data through the socket's input and output streams.
Why should network calls always have a timeout?
Show answer
A read on a socket blocks until data arrives. If the other side has hung or the network has silently dropped the connection, the thread waits indefinitely. In a server, such stuck threads accumulate until the thread pool is exhausted and the whole application stops responding. A connect timeout and a read timeout turn that silent hang into an exception the code can handle or retry.
Key Points to Remember
- Socket is the client-side TCP endpoint; ServerSocket listens and accept() hands back a connected Socket per client.
- URL parses a web address into components; URLConnection performs the actual network I/O to fetch or send data.
- accept() and stream reads block by default, so real servers typically handle each client on a separate thread.
- Modern HTTP work should generally use java.net.http.HttpClient rather than raw sockets or legacy URLConnection.
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
These examples need a JDK project with their libraries on your computer, so they can be copied but not run here. Codelab runs Python, FastAPI backends with SQLite, plain Java 17 and HTML/CSS/JavaScript.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering