Java Sockets
Open TCP client connections in Java with the Socket class.
Java Sockets
Beneath HTTP and every other application protocol sits the socket: a raw, bidirectional TCP connection between two endpoints. Java's java.net.Socket is the client side — you create one, connect it to a host and port, and then read and write bytes through ordinary InputStream/OutputStreams. This is the lowest-level networking you reach for when you speak a custom protocol or talk to a service that is not HTTP.
What a Socket gives you
A connected Socket is a pipe with two streams:
socket.getOutputStream()— bytes you write travel to the other end.socket.getInputStream()— bytes the other end writes arrive here.
TCP guarantees the bytes arrive reliably and in order. It does not impose any message structure — a socket is a stream of bytes, not of messages. Framing (where one message ends and the next begins) is your job: use newlines, length prefixes, or a higher-level protocol.
Connecting
// Style 1: connect in the constructor
Socket socket = new Socket("example.com", 80);
// Style 2: create then connect with a timeout (preferred)
Socket socket = new Socket();
socket.connect(new InetSocketAddress("example.com", 80), 2000);The second form lets you set a connect timeout — without it, an unreachable host can hang the thread for the OS default (often a minute or more). Once connected, wrap the streams in buffered readers/writers and pick a character set explicitly.
Reading and writing text
var out = new PrintWriter(
new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8), true);
var in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
out.println("ping"); // autoFlush=true sends it immediately
String reply = in.readLine(); // blocks until a line arrivesreadLine() blocks until data (or end-of-stream) arrives — the hallmark of the classic blocking socket API. Always close the socket (try-with-resources) to release the connection.
A worked example: a client talking to a loopback echo server
This program starts a one-shot echo server on a background thread bound to the loopback address, then — the chapter's real focus — connects a client Socket, sends a line, and reads the reply. It is a complete TCP conversation inside one JVM, no external network.
What to take from the run:
- The client side is just three steps: construct a
Socket,connect()it to an address and port, then read and write its streams. Everything HTTP did for you in earlier chapters — request lines, headers, status codes — is gone; a socket moves raw bytes and nothing more. connect(new InetSocketAddress(...), 2000)set a 2-second connect timeout. The no-timeout constructornew Socket(host, port)would block on the OS default if the host were unreachable, so the explicit-timeout form is the safer habit for any real network.- The protocol was a convention, not a feature: the client wrote one line and read one line because both sides agreed that lines are messages. TCP delivered an ordered byte stream; the newline framing that turned it into "messages" was entirely application-defined.
readLine()blocked until the server's reply arrived. This thread-per-connection, block-until-data model is simple and correct, and it is exactly the cost theniochannels and virtual threads aim to reduce when connection counts grow large.getRemoteSocketAddress()andgetLocalSocketAddress()showed both ends of the live connection — the server's loopback port and the client's OS-assigned local port. Every TCP connection is identified by that pair of endpoints. The next chapter builds the server side that accepted this connection.
Practice
A client reads from a server using 'socket.getInputStream()' wrapped in a 'BufferedReader', sending one newline-terminated command and expecting one newline-terminated reply. Occasionally a reply is split across two TCP segments and the client misreads it. What is the correct understanding?