Building TCP/IP Applications with Node.js

Most of the times Node.js is used for HTTP-based servers. There are times however when you need to go one level deeper, and write your software based on TCP/IP protocol instead of HTTP. Indeed, HTTP was originally designed as a request-response protocol, and it is text-based. TCP/IP is more "raw": it is binary (meaning, more effective) and also it is full-duplex persistent connectinon (which again means it is more effective). If you are building an application that is not targeted specifically at browsers, there's a good chance that TCP/IP will be a better choice to you than HTTP. In this blog post I will show you how to write such application. A server for chat that is built entirely on TCP/IP. We will not be discussing the client for the chat since building it is much easier, and besides any telnet client can be used to test our Node.js server. We'll be writing all our code in a single file called 'tcp-server.js'. Let's start from making a super simple "echo-server" that sends back all the data to the connected client. Here's the code that does it:
  1. const net = require('net');
  2.  
  3. const server = net.createServer((sock) => {
  4. sock.on('data', (data) => {
  5. sock.write(data);
  6. });
  7. });
  8.  
  9. server.listen(3210, () => {
  10. console.log('opened server on', server.address());
  11. });
Connect to this server with telnet like this:
  1. telnet localhost 3210
NOTE: if you are on windows, download PuttyTel - it is a good Telnet client. Last time I checked, Windows did not have a telnet client built-in. Once you are connected to server, try typing something like 'Hello', and server should send you 'Hello' back. Terminate the connection by pressing Ctrl+] and then type 'quit'. Now we have a basic concept working: clients and servers can exchange messages. However a server is lacking an important feature: detecting when the client is disconnected. With a help of event listeners we can easily handle these cases. Add the following code to our connection listener:
  1. const net = require('net');
  2.  
  3. const server = net.createServer((sock) => {
  4. sock.on('data', (data) => {
  5. sock.write(data);
  6. });
  7.  
  8. sock.on('end', () => {
  9. console.log('client disconnected');
  10. });
  11.  
  12. sock.on('error', () => {
  13. console.log('client socket had error');
  14. });
  15.  
  16. sock.on('close', () => {
  17. console.log('client socket closed');
  18. });
  19. });
  20.  
  21. server.listen(3210, () => {
  22. console.log('opened server on', server.address());
  23. });
Now, whenever there's a disconnect event (due to error, or graceful disconnect), the server will know about it and print the message to a console. Test your server again: try disconnecting gracefully and forcefully and you'll see that all events are properly reported. Up until this point clients did not interact with any other connected clients. Now let's make a chat out of this echo server. Whenever the client is connected, we will be saving his socket in the 'sock' array. Then, whenever there is a message from one of the clients we will be broadcasting this message back to every connected socket.
  1. const net = require('net');
  2.  
  3. const sockets = [];
  4.  
  5. const server = net.createServer((sock) => {
  6.  
  7. sockets.push(sock);
  8.  
  9. sock.on('data', (data) => {
  10. sockets.forEach((s) => s.write(data));
  11. });
  12.  
  13. sock.on('end', () => {
  14. console.log('client disconnected');
  15. });
  16.  
  17. sock.on('error', () => {
  18. console.log('client socket had error');
  19. });
  20.  
  21. sock.on('close', () => {
  22. const idx = sockets.indexOf(sock);
  23. if (idx !== -1) {
  24. sockets.splice(idx, 1);
  25. }
  26.  
  27. console.log('client socket closed');
  28. });
  29. });
  30.  
  31. server.listen(3210, () => {
  32. console.log('opened server on', server.address());
  33. });
And that's all you need to do to make a functional TCP/IP chat! Of course for production use I would consider a little bit more sophisticated protocol, tagging messages with timestamps or maybe adding smileys and colors. This might be a great exercise to develop your Node.js skills! Happy chatting!

Add new comment