Skip to content

Instantly share code, notes, and snippets.

@sid24rane
Last active February 7, 2024 08:05
Show Gist options
  • Save sid24rane/2b10b8f4b2f814bd0851d861d3515a10 to your computer and use it in GitHub Desktop.
Save sid24rane/2b10b8f4b2f814bd0851d861d3515a10 to your computer and use it in GitHub Desktop.
Simple TCP Client and Server in Node.js (Covering all useful Properties & Methods)
var net = require('net');
// creates the server
var server = net.createServer();
//emitted when server closes ...not emitted until all connections closes.
server.on('close',function(){
console.log('Server closed !');
});
// emitted when new client connects
server.on('connection',function(socket){
//this property shows the number of characters currently buffered to be written. (Number of characters is approximately equal to the number of bytes to be written, but the buffer may contain strings, and the strings are lazily encoded, so the exact number of bytes is not known.)
//Users who experience large or growing bufferSize should attempt to "throttle" the data flows in their program with pause() and resume().
console.log('Buffer size : ' + socket.bufferSize);
console.log('---------server details -----------------');
var address = server.address();
var port = address.port;
var family = address.family;
var ipaddr = address.address;
console.log('Server is listening at port' + port);
console.log('Server ip :' + ipaddr);
console.log('Server is IP4/IP6 : ' + family);
var lport = socket.localPort;
var laddr = socket.localAddress;
console.log('Server is listening at LOCAL port' + lport);
console.log('Server LOCAL ip :' + laddr);
console.log('------------remote client info --------------');
var rport = socket.remotePort;
var raddr = socket.remoteAddress;
var rfamily = socket.remoteFamily;
console.log('REMOTE Socket is listening at port' + rport);
console.log('REMOTE Socket ip :' + raddr);
console.log('REMOTE Socket is IP4/IP6 : ' + rfamily);
console.log('--------------------------------------------')
//var no_of_connections = server.getConnections(); // sychronous version
server.getConnections(function(error,count){
console.log('Number of concurrent connections to the server : ' + count);
});
socket.setEncoding('utf8');
socket.setTimeout(800000,function(){
// called after timeout -> same as socket.on('timeout')
// it just tells that soket timed out => its ur job to end or destroy the socket.
// socket.end() vs socket.destroy() => end allows us to send final data and allows some i/o activity to finish before destroying the socket
// whereas destroy kills the socket immediately irrespective of whether any i/o operation is goin on or not...force destry takes place
console.log('Socket timed out');
});
socket.on('data',function(data){
var bread = socket.bytesRead;
var bwrite = socket.bytesWritten;
console.log('Bytes read : ' + bread);
console.log('Bytes written : ' + bwrite);
console.log('Data sent to server : ' + data);
//echo data
var is_kernel_buffer_full = socket.write('Data ::' + data);
if(is_kernel_buffer_full){
console.log('Data was flushed successfully from kernel buffer i.e written successfully!');
}else{
socket.pause();
}
});
socket.on('drain',function(){
console.log('write buffer is empty now .. u can resume the writable stream');
socket.resume();
});
socket.on('error',function(error){
console.log('Error : ' + error);
});
socket.on('timeout',function(){
console.log('Socket timed out !');
socket.end('Timed out!');
// can call socket.destroy() here too.
});
socket.on('end',function(data){
console.log('Socket ended from other end!');
console.log('End data : ' + data);
});
socket.on('close',function(error){
var bread = socket.bytesRead;
var bwrite = socket.bytesWritten;
console.log('Bytes read : ' + bread);
console.log('Bytes written : ' + bwrite);
console.log('Socket closed!');
if(error){
console.log('Socket was closed coz of transmission error');
}
});
setTimeout(function(){
var isdestroyed = socket.destroyed;
console.log('Socket destroyed:' + isdestroyed);
socket.destroy();
},1200000);
});
// emits when any error occurs -> calls closed event immediately after this.
server.on('error',function(error){
console.log('Error: ' + error);
});
//emits when server is bound with server.listen
server.on('listening',function(){
console.log('Server is listening!');
});
server.maxConnections = 10;
//static port allocation
server.listen(2222);
// for dyanmic port allocation
server.listen(function(){
var address = server.address();
var port = address.port;
var family = address.family;
var ipaddr = address.address;
console.log('Server is listening at port' + port);
console.log('Server ip :' + ipaddr);
console.log('Server is IP4/IP6 : ' + family);
});
var islistening = server.listening;
if(islistening){
console.log('Server is listening');
}else{
console.log('Server is not listening');
}
setTimeout(function(){
server.close();
},5000000);
//---------------------client----------------------
// creating a custom socket client and connecting it....
var client = new net.Socket();
client.connect({
port:2222
});
client.on('connect',function(){
console.log('Client: connection established with server');
console.log('---------client details -----------------');
var address = client.address();
var port = address.port;
var family = address.family;
var ipaddr = address.address;
console.log('Client is listening at port' + port);
console.log('Client ip :' + ipaddr);
console.log('Client is IP4/IP6 : ' + family);
// writing data to server
client.write('hello from client');
});
client.setEncoding('utf8');
client.on('data',function(data){
console.log('Data from server:' + data);
});
setTimeout(function(){
client.end('Bye bye server');
},5000);
//NOTE:--> all the events of the socket are applicable here..in client...
// -----------------creating client using net.connect instead of custom socket-------
// server creation using net.connect --->
// u can also => write the below code in seperate js file
// open new node instance => and run it...
const clients = net.connect({port: 2222}, () => {
// 'connect' listener
console.log('connected to server!');
clients.write('world!\r\n');
});
clients.on('data', (data) => {
console.log(data.toString());
clients.end();
});
clients.on('end', () => {
console.log('disconnected from server');
});
@adrwh
Copy link

adrwh commented Feb 18, 2019

Epic, looks awesome.. how would the client write subsequent messages back to the server, like in a tcp chat room style?

@atesztoth
Copy link

Nice gist!

@thisisarjun
Copy link

Awesome.

@AdharshKrish
Copy link

Thankyou so much. This is even better than nodejs documentation

@phifogg
Copy link

phifogg commented Apr 30, 2020

Epic, looks awesome.. how would the client write subsequent messages back to the server, like in a tcp chat room style?

same question... subscribing

@fdl333
Copy link

fdl333 commented Jul 22, 2020

I get:
Error [ERR_SERVER_ALREADY_LISTEN]: Listen method has been called more than once without closing.

As soon as I launch the program ... tried googling, seems a common problem, but found no solution. ANy help pls?

@andreiskandar
Copy link

I am new to this concept and currently doing a project to use 'net' and 'fs' module from node where a client request a file from the server then the server looks for the requested file locally. if file exists and found, then the server sends back the data to the client. I wonder what socket event listener should I use to complete this query?

@wcoffin-livly
Copy link

I get:
Error [ERR_SERVER_ALREADY_LISTEN]: Listen method has been called more than once without closing.

As soon as I launch the program ... tried googling, seems a common problem, but found no solution. ANy help pls?

Same issue - any help would be appreciated. Running with Node v12 on Windows.

@sampirat
Copy link

I get:
Error [ERR_SERVER_ALREADY_LISTEN]: Listen method has been called more than once without closing.
As soon as I launch the program ... tried googling, seems a common problem, but found no solution. ANy help pls?

Same issue - any help would be appreciated. Running with Node v12 on Windows.

Lines 131 & 135-143 : choose one method for listening (static or dynamic) and comment out the other

@hamid814
Copy link

NICE

@Malfix25
Copy link

Malfix25 commented Mar 4, 2021

Epic, looks awesome.. how would the client write subsequent messages back to the server, like in a tcp chat room style?

I have this question as well.

@sampirat
Copy link

sampirat commented Mar 4, 2021

Epic, looks awesome.. how would the client write subsequent messages back to the server, like in a tcp chat room style?

I have this question as well.

line 182
// writing data (from client) to server
client.write('hello from client');

@Malfix25
Copy link

Malfix25 commented Mar 4, 2021

Epic, looks awesome.. how would the client write subsequent messages back to the server, like in a tcp chat room style?

I have this question as well.

line 182
// writing data (from client) to server
client.write('hello from client');

Whoops, my bad, I guess I should have examined the example code closer, thanks!

@sampirat
Copy link

sampirat commented Mar 4, 2021

Don't worry ;)

@micromotores
Copy link

how send data from server to especific connection ?

@borisStanojevic
Copy link

borisStanojevic commented Nov 20, 2022

@andreiskandar The data event. Send the file search request (message) from the client, process the request in the data event handler, and return back the result via the write method.

@borisStanojevic
Copy link

borisStanojevic commented Nov 20, 2022

@micromotores Keep track of the connections (sockets) in an array or an object. Each time there is a connection event you put the socket object into the sockets structure and each time there is a an end event you remove the socket from the structure. This will allow you to broadcast a message to all connected sockets.

To send data to a specific socket you would need to somehow uniquely identify it. For this scenario, it makes sense for the above mentioned structure to be an object (a hash table) of sockets. You can send a special message from the client right after the connection was established. The message would contain the unique ID of the client and you would add an entry to the mentioned sockets objects on the server side once it receives the message.

Using an object instead of an array to keep track of sockets would be favorable in case of large number of connections. Adding a socket to the array would have constant (O(1)) amortized time complexity but removal of the the socket from an array would have linear (O(n)) time complexity. In case of an object, both operations would have constant (O(1)) time complexity.

@asadnobi
Copy link

Great!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment