Node has a simple API for creating TCP connections and servers. Most of the lowest level classes and methods can be found in the net module. Here, you’ll learn how to create a TCP server and track the clients that connect to it. The cool thing about this is that higher-level protocols like HTTP are built on top of the TCP API, so once you’ve got the hang of TCP clients and servers, you can really start to exploit some of the more subtle features of the HTTP API as well.
The server object itself is an instance of net.Server, which is just a wrapper around the net.Socket class. It’s interesting to note that net.Socket is implemented using a duplex stream.
---------------------------Server Program ------------------------ var net = require('net'); var clients = 0; var server = net.createServer(function(client) { clients++; var clientId = clients; console.log('Client Connected', clientId); client.on('end', function() { console.log('Client disconnected:', clientId); }) //client.write('Welcome client: ' + clientId + '\n'); client.pipe(client); }); server.listen(8000, function() { console.log('Server Started on port 8000'); })
--------------------------- Client Program -------------------------- var net = require('net'); const readline = require('readline'); const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); var client = net.connect(8000); console.log('Connected to Server !!! - Enter Text (Quit to stop)') var ask = function() { rl.question('', (value) => { if (value.toString() != 'Quit') { client.write(value.toString()); ask(); } else { rl.close(); client.end(); return; } }); } ask(); client.on('data', function(data) { console.log(data.toString()); }); client.on('end', function() { console.log('I have disconnected !!!') });
Exercise – Write down TCP Client Server Application using nodejs in which client sends one string to the server and server returns with the message whether the string is palindrome or not.
Solution : PalindromeServer.js PalindromeClient.js
Compared to TCP, UDP is a much simpler protocol. That can mean more work for you: rather than being able to rely on data being sent and received, you have to cater to UDP’s more volatile nature. UDP is suitable for query-response protocols, which is why it’s used for the Domain Name System (DNS). It’s also stateless—if you want to
transfer data and you value lower latency over data integrity, then UDP is a good choice. That might sound unusual, but there are applications that fit these characteristics: media streaming protocols and online games generally use UDP.
If you wanted to build a video streaming service, you could transfer video over TCP, but each packet would have a lot of overhead for ensuring delivery. With UDP, it would be possible for data to be lost with no simple means of discovery, but with video you don’t care about occasional glitches—you just want data as fast as possible. In fact,
some video and image formats can survive a small amount of data loss: the JPEG format is resilient to corrupt bytes to a certain extent.
The next technique combines Node’s file streams with UDP to create a simple server that can be used to transfer files. Although this can potentially result in data loss, it can be useful when you care about speed over all else.
Transferring a file with UDP
This technique is really about sending data from a stream to a UDP server rather than creating a generalized file transfer mechanism. You can use it to learn the basics of Node’s datagram API.
■ Problem – You want to transfer data from a client to a server using datagrams.
■ Solution – Use the dgram module to create datagram sockets, and then send data with socket.send.
■ Discussion
Sending datagrams is similar to using TCP sockets, but the API is slightly different, and datagrams have their own rules that reflect the actual structure of UDP packets.
var udp = require('dgram'); // --------------------creating a udp server -------------------- // creating a udp server var server = udp.createSocket('udp4'); // emits when any error occurs server.on('error', function(error) { console.log('Error: ' + error); server.close(); }); // emits on new datagram msg server.on('message', function(msg, info) { console.log('Data received from client : ' + msg.toString()); console.log('Received %d bytes from %s:%d\n', msg.length, info.address, info.port); //sending msg server.send(msg, info.port, 'localhost', function(error) { if (error) { client.close(); } else { console.log('Data sent !!!'); } }); }); //emits when socket is ready and listening for datagram msgs server.on('listening', 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); }); //emits after the socket is closed using socket.close(); server.on('close', function() { console.log('Socket is closed !'); }); server.bind(2222); setTimeout(function() { server.close(); }, 8000);
var buffer = require('buffer'); var udp = require('dgram'); // creating a client socket var client = udp.createSocket('udp4'); //buffer msg var data = Buffer.from('TusharGohil'); client.on('message', function(msg, info) { console.log('Data received from server : ' + msg.toString()); console.log('Received %d bytes from %s:%d\n', msg.length, info.address, info.port); }); //sending msg client.send(data, 2222, 'localhost', function(error) { if (error) { client.close(); } else { console.log('Data sent !!!'); } }); var data1 = Buffer.from('hello'); var data2 = Buffer.from('world'); //sending multiple msg client.send([data1, data2], 2222, 'localhost', function(error) { if (error) { client.close(); } else { console.log('Data sent !!!'); } }); client.on('close', function() { console.log('Client Socket is closed !'); }); setTimeout(function() { client.close(); }, 8000);
Even though this is a simple example, it’s immediately obvious how UDP is different from TCP—you need to pay attention to the size of the messages you send, and realize that it’s possible for messages to get lost. Although datagrams have a checksum, lost or damaged packets aren’t reported to the application layer, which means data loss is possible. It’s generally best to use UDP for sending data where assured integrity is second place to low latency and throughput.