Memra

Constructing, connecting, and interrogating a socket

◈ 4 cards

Split construction from connection with Socket() plus connect(SocketAddress, timeout), tell the connect timeout from the read timeout, and read a socket's state without being fooled by isConnected().

Four constructors, one blocking act

Every Socket constructor that takes a host and a port connects before it returns:

  • Socket(String host, int port) — resolves the name, then connects.
  • Socket(InetAddress host, int port) — connects to an address you already resolved.
  • Two four-argument variants that additionally pin the local address and port you connect from, for multi-homed machines.

The remote port is an int from 1 to 65535. The local port, if you do not specify one, is chosen by the operating system from the free ephemeral range — which is why two connections from the same machine to the same server are distinguishable at all.

Splitting construction from connection

The no-argument Socket() constructor builds an unconnected socket and throws nothing, because it has nowhere to go. You connect it later:

socket.connect(SocketAddress endpoint)
socket.connect(SocketAddress endpoint, int timeout)

Two reasons to want this. First, a handful of socket options can only be set before the connection exists, and this is the only way to reach them. Second — the one you will use daily — the two-argument form is the only way to bound how long the connection attempt itself may take. There is no constructor that takes a connect timeout.

The endpoint is a SocketAddress. That class is abstract and method-free; in practice the only implementation you ever use is InetSocketAddress, built as new InetSocketAddress(host, port). Its real value is that it outlives the socket: you can pull getRemoteSocketAddress() off a connection, close it, and reconnect to the same endpoint later without re-typing the host and port.

Two different timeouts

This is the distinction the exam likes and beginners collapse:

  • connect(address, 5_000) bounds the handshake. Too slow, and you get a SocketTimeoutException before you ever have a usable socket.
  • setSoTimeout(10_000) bounds each individual read on an established connection.

They are independent. A client with only one of them still has a way to hang. The connect timeout defaults to 0, which means wait as long as the operating system will — often more than a minute.

What a socket will tell you about itself

Four getters expose the endpoints, and there are no setters — the values are fixed the moment the connection is made: getInetAddress() and getPort() for the remote end, getLocalAddress() and getLocalPort() for your end, plus getRemoteSocketAddress() and getLocalSocketAddress() returning them as SocketAddress objects (both null before the socket connects).

The state predicates need more care because they are sticky: isBound() and isConnected() report whether the socket was ever bound or connected, and closing does not clear either. So isConnected() on a closed socket returns true. The correct test for "open right now" is isConnected() && !isClosed().

shutdownOutput() half-closes: your peer's next read returns end-of-stream, so it knows your request is complete, while its replies still reach you. Any further write of yours throws IOException. shutdownInput() is the mirror. isOutputShutdown() and isInputShutdown() report each half. Neither shutdown releases the socket's resources, so you still call close().

Worked example — a connect with a deadline

Build the socket unconnected, connect it to an InetSocketAddress with a five-second handshake budget, set a ten-second read budget, then print both endpoints. The remote address is the one you asked for; the local port is whatever the OS handed you, and it differs on every run.

momentisBound()isConnected()isClosed()new Socket()falsefalsefalseafter connect(addr,5000)truetruefalseafter close()truetruetrueOpen now = isConnected() && !isClosed().
Read the bottom row carefully: after close(), isConnected() is still true. The predicates answer "did this ever happen", not "is this true now", so the only correct liveness test is isConnected() && !isClosed().

source Harold 4e ch8 §Closed or Connected?; JDK javadoc java.net.Socket#isBound, #isConnected

NORMAL ~/memra/learn/comp-348/connecting-and-interrogating-sockets utf-8 LF