TCP Sockets with net

node:net is the layer HTTP is built on, Stability 2 – Stable. A net.Server hands you a net.Socket per connection — an ordinary duplex stream, so Buffers and Streams applies unchanged — but not messages: TCP delivers bytes, so two socket.write calls can arrive as one data event and one write as three. Every protocol on TCP needs framing, here newlines.

A line-framed TCP server, with a client in the same fileJavaScript
import { createServer, connect } from 'node:net';
const server = createServer({ noDelay: true }, (socket) => {
  socket.setEncoding('utf8'); let buf = '';   // TCP is a byte stream, not a message stream
  socket.on('data', (chunk) => {
    buf += chunk;
    for (let i; (i = buf.indexOf('\n')) !== -1; buf = buf.slice(i + 1))
      socket.write(buf.slice(0, i).toUpperCase() + '\n');
  });
});
server.listen(7070, '127.0.0.1', async () => {
  const client = connect(7070, '127.0.0.1').setEncoding('utf8');
  client.end('hello from node\nbye for now\n');
  for await (const chunk of client) process.stdout.write('<- ' + chunk);
  server.close();
});
Output
<- HELLO FROM NODE
BYE FOR NOW

socket.setTimeout(ms) emits timeout after inactivity but closes nothing, so your handler must call socket.destroy(), and errors arrive as error events, never exceptions.