10X Sale
kh logo
All Courses
  1. Tutorials
  2. Web Development

Socket Services

Updated on Aug 29, 2025
 
14,485 Views

In this topic, we are going to understand and implement the network API for creating stream-based on TCP and TLS servers. Will also implement the corresponding client to consume and interact with the server. Node.js provides two modules to create server and client to establish and maintain a network conversation.

  1. Net - https://nodejs.org/api/net.html [TCP]
  2. TSL - https://nodejs.org/api/tls.html [TLS]

Let’s start with the net module for implementing TCP server and client.

TCP Server

- Create a file tcpServer.js and import the net module.

var net = require(‘net’); 

- Create the server using createServer which takes call back

var server = net.createServer(); 

- Lets listen to the server on a given port and host.

server.listen(port, host, () => { 
console.log(`TCP server listening on ${host}:${port}`); 
});

For now, we can configure host as local host and port as some arbitrary number 1234

- Have an event handler on the server when any client gets connected. So lets built it

server.on(‘connection’,  (socket) => { 
var clientAddress = `${socket.remoteAddress}:${socket.remotePort}`; 
console.log(`new client connected: ${clientAddress}`); 
 });

- Also lets listen to few events on the socket like data, close and error.

socket.on('data', (data) => { 
    console.log(`${clientAddress}: ${data}`); 
 }); 
 socket.on('close',  () => { 
    console.log(`connection closed: ${clientAddress}`); 
 }); 
  socket.on('error', (err) => { 
    console.log(`Error occurred in ${clientAddress}: ${err.message}`); 
  });

- Since server can be connected to multiple clients, let store them in an array.

(socket) => { 
var clientAddress = `${sock.remoteAddress}:${sock.remotePort}`; 
console.log(`new client connected: ${clientAddress}`); 
sockets.push(socket); 
… 
 }

- Propagate the message from one client to all other clients.

socket.on('data', (data) => { 
console.log(`${clientAddress}: ${data}`); 
sockets.forEach((sock) => { 
sock.write(`${sock.remoteAddress}:${sock.remotePort} said ${data}\n`); 
}); 
 });

- On close of specific client, lets remove from sockets array and notify that this client is disconnected.

socket.on('close', (data) => { 
        const index = sockets.findIndex( (o) => { 
            return (o.remoteAddress===socket.remoteAddress) && 
(o.remotePort === socket.remotePort); 
        }); 
        if (index !== -1) sockets.splice(index, 1); 
sockets.forEach((sock) => { 
sock.write(`${clientAddress} disconnected\n`); 
}); 
console.log(`connection closed: ${clientAddress}`); 
    });

- Run node tcpServer.js and see that we don’t have any errors. Now we have a fully functional TCP server running which can accommodate multiple clients.

constnet = require('net'); 
constport = 1234; 
consthost = 'localhost'; 
constserver = net.createServer(); 
server.listen(port, host, () => { 
console.log(`TCP server listening on ${host}:${port}`); 
}); 
letsockets = []; 
server.on('connection', (socket) => { 
varclientAddress = `${socket.remoteAddress}:${socket.remotePort}`; 
console.log(`new client connected: ${clientAddress}`); 
sockets.push(socket); 
socket.on('data', (data) => { 
console.log(`Client ${clientAddress}: ${data}`); 
// Write the data back to all the connected, the client will receive it as data from the server 
sockets.forEach((sock) => { 
sock.write(socket.remoteAddress + ':' + socket.remotePort + " said " + data + '\n'); 
        }); 
    }); 
// Add a 'close' event handler to this instance of socket 
socket.on('close', (data) => { 
letindex = sockets.findIndex((o) => { 
returno.remoteAddress === socket.remoteAddress && o.remotePort === socket.remotePort; 
        }) 
if (index !== -1) sockets.splice(index, 1); 
sockets.forEach((sock) => { 
sock.write(`${clientAddress} disconnected\n`); 
        }); 
console.log(`connection closed: ${clientAddress}`); 
    }); 
// Add a 'error' event handler to this instance of socket 
socket.on('error', (err) => { 
console.log(`Error occurred in ${clientAddress}: ${err.message}`); 
    }); 
});

TCP Client: For TCP client creation, we use the same module i.e. ‘net’.

- Create a file tcpClient.js and import the net module.

var net = require(‘net’); 

- Copy the host and port from the server file.
- Create the client using Socket method.

var client = new net.Socket(); 

- Now that client is created, let's make it connect to the server and send some message. So that server can echo back the same to all clients

client.connect( port, host, () => { 
console.log(`client connected to ${host}:${port}`); 
client.write(‘Hello, I am ${client.address().address}); 
});

- Lets listen to some events similar to server like data, close and error.

client.on('data', (data) => {     
    console.log(`Client received: ${data}`); 
});  
// Add a 'close' event handler for the client socket 
client.on('close', () => { 
    console.log('Client closed'); 
});  
client.on('error', (err) => { 
    console.error(err); 
});

- To disconnect, lets listen to ‘exit’ in data event.

client.on(‘data’, (data) => { 
… 
if (data.toString().endsWith('exit')) { 
       client.destroy(); 
} 
});

- Run node tcpClient in a new terminal as server is running already.
- Observe that the client has connected and got the message from the server.
- Switch to the server terminal and observe that new client is connected. And send some message as well.
- We can start multiple clients and see that they communicate with each other via a single server.

varnet = require('net'); 
constHOST = 'localhost'; 
constPORT = 1234; 
varclient = newnet.Socket(); 
client.connect(PORT, HOST, () => { 
console.log(`client connected to ${HOST}:${PORT}`); 
// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client  
client.write(`Hello, I am ${client.address().address}`); 
}); 
client.on('data', (data) => {     
console.log(`Client received: ${data}`); 
if (data.toString().endsWith('exit')) { 
client.destroy(); 
    } 
}); 
// Add a 'close' event handler for the client socket 
client.on('close', () => { 
console.log('Client closed'); 
}); 
client.on('error', (err) => { 
console.error(err); 
});

Sometimes the interaction with the server might be asynchronous and we may want to use the promise object. Let’s extend the above client in those lines by creating a class object.

- Create a new Client.js file and create a class Client with host and port as constants.

const net = require('net'); 
const PORT = 1234, HOST = 'localhost'; 
class Client {}

- Create a construction in which we would like to create a socket and initialize it.

constructor() { 
   this.socket = new new.socket(); 
   this.port = PORT; 
   this.address = HOST; 
   this.init(); 
}

- In init, we would to connect the client to server and listen to close event.

init() { 
  var client = this; 
  client.socket.connect(client.port, client.address, () => { 
console.log(`Client connected to: ${client.address} :  ${client.port}`); 
  });  
  client.socket.on('close', () => { 
   console.log('Client closed'); 
  }); 
 }

- Lets create a sendMessage method for sending message to server and returning a promise.

sendMessage(message) { 
var client = this; 
return new Promise((resolve, reject) => { 
client.socket.write(message); 
client.socket.on('data', (data) => { 
resolve(data); 
if (data.toString().endsWith('exit')) { 
client.socket.destroy(); 
} 
}); 
client.socket.on('error', (err) => { 
        reject(err); 
}); 
}); 
 }

- Export this class module.exports = Client;

constnet = require('net'); 
constPORT = 1234, HOST = 'localhost'; 
classClient { 
constructor(port, address) { 
this.socket = newnet.Socket(); 
this.address = address || HOST; 
this.port = port || PORT; 
this.init(); 
 } 
init() { 
varclient = this; 
client.socket.connect(client.port, client.address, () => { 
console.log(`Client connected to: ${client.address} : ${client.port}`); 
  }); 
client.socket.on('close', () => { 
console.log('Client closed'); 
  }); 
 } 
sendMessage(message) { 
varclient = this; 
returnnewPromise((resolve, reject) => { 
client.socket.write(message); 
client.socket.on('data', (data) => { 
resolve(data); 
if (data.toString().endsWith('exit')) { 
client.socket.destroy(); 
    } 
   }); 
client.socket.on('error', (err) => { 
reject(err); 
   }); 
  }); 
 } 
} 
module.exports = Client;

- Create a new tcpPromisifyClient.js and import the client to create an instance

const Client = require(./client’); 
const promisifyClient = new Client();

- Lets send the message from client and then chain it.

promisifyClient.sendMessage(‘Hi’) 
.then((data) => { 
console.log(`Received: ${data}`); 
return promisifyClient.sendMessage('How are you'); 
}).then((data) => { 
console.log(`Received: ${data}`); 
return promisifyClient.sendMessage('Bye'); 
}).then((data) => { 
console.log(`Received: ${data}`); 
return promisifyClient.sendMessage('exit'); 
}).catch((err) => console.error(err));  

- Run node tcpPromisifyClient and observe that client connected and observe that messages are send and received.

- The same thing can be observed on the server side as well.

constClient = require('./Client'); 
constpromisifyClient = newClient(); 
promisifyClient.sendMessage('Hi') 
.then((data) => { 
console.log(`Received: ${data}`); 
returnpromisifyClient.sendMessage('How are you'); 
}).then((data) => { 
console.log(`Received: ${data}`); 
returnpromisifyClient.sendMessage('Bye'); 
}).then((data) => { 
console.log(`Received: ${data}`); 
returnpromisifyClient.sendMessage('exit'); 
}).catch((err) =>console.error(err));  

TLS (SSL) :

The ‘TLS’ module provides an implementation of Transport Layer Security (TLS) and Secure Socket Layer (SSL) protocols that are built on top of OpenSSL.

Understanding the Concepts: The TLS/SSL is a public/private key infrastructure (PKI). Each client and server must have a private key. A private key can be generated using the OpenSSL command-line interface.

With TLS/SSL, all server (and some clients) must have a certificate. Certificates are public keys that correspond to a private key, and that are digitally signed either by a Certificate Authority or by the owner of the private key (such certificates are referred to as "self-signed").

The only major differences between this and regular TCP connection are the private key and public certificate that you’ll have to set into an options object.

Before going further let's create the key and certificate (self-signed) using OpenSSL.

Key: openssl genrsa -out private-key.pem 1024

Certificate: openssl req -new -key private-key.pem -out csr.pem

Self-signed: openssl x509 -req -in csr.pem -signkey private-key.pem -out public-cert.pem

TLS Socket Server:

- Create tlsServer.js file and import the tls module along with fs.

var tls = require(‘tls’); 
var fs = require(‘fs’);

- For server, we need to provide options about key and cert, let load them using fs module

var options = { 
   key: fs.readFileSync(private-key.pem’), 
   cert: fs.readFileSync(public-cert.pem’) 
};

- Now we are good to start the server with options and a callback similar to what we did for TCP.

var server = tls.createServer(options, function(socket) { 
socket.write("I am the server sending you a message."); 
// Print the data that we received 
socket.on('data', function(data) { 
      console.log(`Received:${data.toString()}`);  
}); 
// Let us know when the transmission is over 
socket.on('end', function() { 
        console.log('EOT (End Of Transmission)'); 
}); 
});

- Start listening on a specific port and address.

server.listen(PORT, HOST, () =>  console.log(TLS Server started listening’) ); 

- Add an event handler for error.

// When an error occurs, show it. 
server.on('error', function(error) { 
    console.error(error); 
    // Close the connection after the error occurred. 
    server.destroy(); 
});

- Run node tlsServer and observe that server started message in console.

vartls = require('tls'); 
varfs = require('fs'); 
constPORT = 1234; 
constHOST = 'localhost' 
varoptions = { 
key:fs.readFileSync('private-key.pem'), 
cert:fs.readFileSync('public-cert.pem') 
}; 
varserver = tls.createServer(options, function(socket) { 
// Send a friendly message 
socket.write("I am the server sending you a message."); 
// Print the data that we received 
socket.on('data', (data) => { 
console.log(`Received:${data.toString()}`) 
    }); 
// Let us know when the transmission is over 
socket.on('end', function() { 
console.log('EOT (End Of Transmission)'); 
    }); 
}); 
// Start listening on a specific port and address 
server.listen(PORT, HOST, function() { 
console.log("I'm listening at %s, on port %s", HOST, PORT); 
}); 
// When an error occurs, show it. 
server.on('error', function(error) { 
console.error(error); 
// Close the connection after the error occurred. 
server.destroy(); 
});

TLS Socket Client: Lets create a TLS client.

- Create tlsClient.js and import tls and fs modules.

var tls = require('tls'); 
var fs = require('fs');

- We need to create options key and cert. Also, our certificate is self-signed and NodeJS server won’t trust such a certificate by default. So for now, we can rely on option rejectUnauthorized: false.

// Pass the certs to the server and let it know to process even unauthorized certs. 
var options = { 
    key: fs.readFileSync('private-key.pem'), 
    cert: fs.readFileSync('public-cert.pem'), 
    rejectUnauthorized: false 
};

- Connect to the server at the specified port and host. Also check if it is authorized in the call back.

var client = tls.connect(PORT, HOST, options, function() { 
// Check if the authorization worked 
if (client.authorized) { 
       console.log("Connection authorized by a Certificate Authority."); 
} else { 
       console.log(`Connection not authorized: ${client.authorizationError}`); 
} 
// Send a friendly message 
client.write(`client connected to ${HOST}:${PORT}`); 
});

- Add event handler for data, close and error.

client.on("data", (data) => { 
    console.log(`Received:${data}`); 
}); 
client.on('close', () =>  console.log("Connection closed")); 
// When an error occurs, show it. 
client.on('error', (error) => {  
     console.error(error); 
     // Close the connection after the error occurred. 
     client.destroy(); 
});

- Create a new terminal and run tlsClient.js.
- Observe that the client connected and observe that messages are sent and received.
- The same thing can be observed on the server side as well.

vartls = require('tls'); 
varfs = require('fs'); 
constPORT = 1234; 
constHOST = 'localhost' 
// Pass the certs to the server and let it know to process even unauthorized certs. 
varoptions = { 
key:fs.readFileSync('private-key.pem'), 
cert:fs.readFileSync('public-cert.pem'), 
rejectUnauthorized:false 
}; 
varclient = tls.connect(PORT, HOST, options, function() { 
// Check if the authorization worked 
if (client.authorized) { 
console.log("Connection authorized by a Certificate Authority."); 
    } else { 
console.log(`Connection not authorized: ${client.authorizationError}`); 
    } 
// Send a friendly message 
client.write(`client connected to ${HOST}:${PORT}`); 
}); 
client.on("data", (data) => { 
console.log(`Received: ${data}`); 
}); 
client.on('close', () => { 
console.log("Connection closed"); 
}); 
// When an error ocoures, show it. 
client.on('error', (error) => { 
console.error(error); 
// Close the connection after the error occurred. 
client.destroy(); 
});
+91

By Signing up, you agree to ourTerms & Conditionsand ourPrivacy and Policy

Get your free handbook for CSM!!
Recommended Courses