Net

Understand the workings of the net module in Node.js.

TCP

One of the most common transport layer protocols is TCPTransmission Control Protocol. It provides a reliable way of sending packets in an ordered and error-checked stream. TCP is connection-oriented, which means that a connection must be established between the client and the server before data can be sent. We will not delve into the details of how that works, as that is beyond the scope here. Still, it is important to know how it works, as it will help us understand the difference between TCP and UDP.

net

The net module provides an asynchronous network API for creating stream-based TCP or IPCInter-Process Communication servers. Let’s see how we can make a simple TCP server. Run the code below.

var net = require("net");

var server = net.createServer();
const port = 3500;

server.on("connection", function (socket) {
  console.log("Client connected from", socket.remoteAddress, socket.remotePort);
  socket.write("Hello from the server!");

  socket.on("data", function (data) {
    console.log("Msg from client:", data.toString());
  });

  socket.on("close", function (err) {
    if (err) {
      console.log("Client disconnected due to error");
    } else {
      console.log("Client disconnected");
    }
  });
});

server.on("listening", function () {
  console.log("Server is listening on port", port);
});

server.listen(port);
Use ctrl + b, followed by a direction key, to switch panes in the terminal

This simple TCP server presents a lot of useful methods of the net module. Let’s explore them further.

The server-side

  • We import the net module on line 1.
  • The createServer method on line 3, as the name suggests, creates a server object. This server is an object of the EventEmitter class; hence, we can use the .on method to handle different events.
  • Declaring our port early in the code and using the variable name will make changing later on easier. We have set the port to 3500 on line 4.
  • The most important event that can be raised is the connection event. This event fires when a new connection to the server is made. As you can see on line 6, this event returns an object that we name socket. This socket object is an instance of net.Socket.
  • The net.Socket also belongs to the EventEmitter class. It also has a few methods and events that can come in handy for creating a server.
  • The remoteAddress and remotePort are two attributes of the net.Socket object that we use to output the IP address and the port of the incoming connection on line 7.
  • We can send data on the socket by using the write method. We pass it a string of our choice, and it is sent to the client. This is done on line 8.
  • The data event is fired when data from a client is received. We are outputting the data on line 10.
  • The close event is fired when a socket is fully closed. This indicates that communication has ended. If the socket close due to an error, the hadError boolean is set to true. We are outputting both cases on line 16 and line 18.
  • For the server object, the listening event is fired when the server starts to listen for incoming connections. We are using this event to output a string to let us know that the server is up. This is done on line 23.
  • Finally, to start the server, we use the .listen() method. It is passed a port number. Now our server is live and waiting for new connections.

The client-side

  • Looking from the other side, the client-side, another useful method is the net.connect() method. We pass it the port number that our server is listening on, 3500 in our case. This method also returns a net.Socket object like our connection event did on the server-side. This is done on line 8.
  • The data and end methods are used in a similar manner as we have used on the server-side. The end method is similar to the close method in terms of functionality.

Let’s make them talk

Now that our client and server are able to connect with each other, we can use the readline module to send some text from one console to the other over the TCP socket. Let’s see how that can be done.

const net = require("net");
const readline = require("readline");

var server = net.createServer();
const port = 3500;

var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: "",
});

server.on("connection", function (socket) {
  console.log("Client connected from", socket.remoteAddress, socket.remotePort);
  socket.write("Hello from the server!");

  socket.on("data", function (data) {
    console.log("Msg from client:", data.toString());
  });

  rl.prompt();
  rl.on("line", function (line) {
    socket.write(line);
    rl.prompt();
  });

  socket.on("close", function (err) {
    if (err) {
      console.log("Client disconnected due to error");
    } else {
      console.log("Client disconnected");
    }
  });
});

server.on("listening", function () {
  console.log("Server is listening on port", port);
});

server.listen(port);
Hit the RUN button to view the output

The server-side

  • We import the readline module on line 2.
  • We use the createInterface method to use our streams.
  • Instead of using setPrompt, we set it while creating our interface.
  • We have set it to be '', which is just an empty string. This way, the prompt does not interfere with the incoming text from the socket. This is done on line 10.
  • We use the on method to assign a listener to the line event. The listener function callback writes the data from the input stream to the socket. This is done on line 24. We then use the prompt method again to ensure that we are ready to read data from the input stream again.

The client-side

We create an interface and use the same methods as we used in server.js to send text from the console to the server.

Get hands-on with 1300+ tech skills courses.