TCP foundations
Build a TCP client
Connect to the local server, read stream data, handle errors, and observe connection closure.
10 minute lesson
The client is the side that initiates. It needs two things: the server’s address and its port. Together they identify one specific listener on one specific machine.
A TCP client connects to an address and port, then exchanges bytes on the resulting stream. The connection event means the three-way handshake completed; it does not guarantee a useful application response. The server could accept you and then say nothing.
Create client.mjs:
import net from 'node:net'
const socket = net.createConnection({ host: '127.0.0.1', port: 4000 })
socket.on('data', data => process.stdout.write(data))
socket.on('end', () => console.log('server closed'))
socket.on('error', error => console.error(error.message))
net.createConnection() starts the handshake immediately. Each data event delivers whatever bytes the server sent. The end event fires when the server closes its side of the stream.
Run the server from the previous lesson first, then the client:
node client.mjs
# hello from TCP
# server closed
When nobody is listening
Stop the server and run the client again:
node client.mjs
# connect ECONNREFUSED 127.0.0.1:4000
ECONNREFUSED means your packet reached the machine, but no process was listening on that port, so the kernel actively rejected the connection. It’s a different failure from a timeout, where packets vanish and you wait. Refusal is fast and definitive: wrong port, or the server isn’t running.
Seeing connection refusal as a separate failure matters when debugging. Refused points at the server process. A hang points at the network or a firewall.
Sending data too
A real client writes as well as reads. Add a request:
socket.on('connect', () => {
socket.write('PING\n')
})
You can call socket.write() before the connection is up — Node queues the bytes and flushes them after the handshake — but writing inside the connect handler makes the sequence explicit.
Always attach an error handler. An unhandled error event on a socket throws, and that can terminate the whole Node process. Without the handler, a routine network failure like a refused connection becomes a crash.
Lesson completed