Hi Guys,
In this blog post I am going to explain in detail about Building TCP Servers in NodeJs .
What is NodeJs => Node.js is an open-source server side runtime environment built on Chrome’s V8 JavaScript engine. It provides an event driven, non-blocking (asynchronous) I/O and cross-platform runtime environment for building highly scalable server-side application using JavaScript.
WHAT’S IN THIS BLOG
- Creating a TCP server
- Closing server-side TCP connections
- Handling network errors
- Piping data to or from a TCP connection
- Building a TCP chat server
The Transmission Control Protocol (TCP) is one of the fundamental protocols of the Internet. It sits on top of the Internet protocol (IP) and provides a transport mechanism for the application layer. HTTP, for instance, works on top of TCP, as do many other connection-oriented applications such as iRC, SMTP, and IMAP. Node has a first-class HTTP server implementation in the form of a pseudo-class in http.Server , which descends from the TCP server pseudo-class in net.Server .
CREATING A TCP SERVER
You can create a TCP server using the net module like this:
1 2 3 4 5 6 7 8 9 10 11 12 |
<span style="font-size: 12px">var net = require('net'); // import net package from NPM(Node Package Manager)</span> <span style="font-size: 12px">var port = 4001; // port must me 4 digits </span> <span style="font-size: 12px">var server = net.createServer( function(socket) { // you use the <strong>createServer()</strong> method on the <strong>net</strong> package</span> <span style="font-size: 12px">// new Connection</span> <span style="font-size: 12px">socket.on('data' , function() {</span> <span style="font-size: 12px">// got data </span> <span style="font-size: 12px">});</span><span style="font-size: 12px">socket.on('end' ,function() {</span> <span style="font-size: 12px">// connection closed</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">socket.write('Some things');</span> <span style="font-size: 12px">}); server.listen(port);</span> |
you use the createServer() method on the net package, which you bind to TCP port 4000 ,You can pass in a callback function to createServer to be called every time there is a “connection” event.Inside this callback you will be handed a socket object, which you can use to send and receive data to and from the client. Because the server object is also an EventEmitter, and you can listen to events during its lifecycle, net.Server emits the following events:
➤ “listening” — When the server is listening on the specifi ed port and address.
➤ “connection” — When a new connection is established. The callback to this function will receive the corresponding socket object. You can also bind to this event by passing a function to server.createServer() .
➤ “close” — When the server is closed, that is, it’s not bound to that port any more.
➤ “error” — When an error occurs at the server level. An error event happens, for instance, when you try to bind to an occupied port or to a port you don’t have permission to bind to.
Lifecycle example of a TCP server
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<span style="font-size: 12px">var server = require('net').createServer();</span> <span style="font-size: 12px">var port = 4000;</span> <span style="font-size: 12px">server.on('listening', function() {</span> <span style="font-size: 12px">console.log('Server is listening on port', port);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('connection', function(socket) {</span> <span style="font-size: 12px">console.log('Server has a new connection');</span> <span style="font-size: 12px">socket.end();</span> <span style="font-size: 12px">server.close();</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('close', function() {</span> <span style="font-size: 12px">console.log('Server is now closed');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('error', function(err) {</span> <span style="font-size: 12px">console.log('Error occurred:', err.message);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.listen(port);</span> |
You can launch this example and, while the server is running, connect to it by using telnet or nc like so:
$ telnet localhost 4000
or
$ nc localhost 4000
Once you connect, the server will disconnect you and then close You should see the following output on the server console:
Server is listening on port 4000
Server has a new connection
Server is now closed
Using the Socket Object
When you get a “connection” event you are also handed the socket object as the first argument of the callback function. This socket object is both a read and a write stream, which means that it emits “data” events when it gets a package of data and emits the “end” event when that connection is closed. Because the socket object is also a writable stream, that means you can write buffers or strings to the socket by using socket.write() . You can tell the socket that it should terminate the connection after all data has been written by calling socket.end() .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span style="font-size: 16px"><strong>Simple echo TCP server</strong></span> <span style="font-size: 12px"> var net = require('net') var server = net.createServer(function(socket) {</span> <span style="font-size: 12px">console.log('new connection');</span> <span style="font-size: 12px">socket.setEncoding('utf8');</span> <span style="font-size: 12px">socket.write("Hello! you can type 'quit' for exit......\n");</span> <span style="font-size: 12px">socket.on('data', function(data) {</span> <span style="font-size: 12px">console.log('got:', data.toString())</span> <span style="font-size: 12px">if (data.trim().toLowerCase() === 'quit') {</span> <span style="font-size: 12px">socket.write('Bye bye!');</span> <span style="font-size: 12px">return socket.end();</span> <span style="font-size: 12px">}</span> <span style="font-size: 12px">socket.write(data);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">socket.on('end', function() {</span> <span style="font-size: 12px">console.log('Client connection ended');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">}).listen(4000);</span> |
Again, you can start this server, connect to it using telnet or nc , as you did before, and play around with it. You can type quit<enter> to terminate the connection.
1 2 3 4 5 6 7 |
<span style="font-size: 14px"><strong><span style="font-size: 16px">Closing the Server</span> </strong>var server = ... server.close(); // preventing it from accepting new connections(<strong>asynchronous</strong>) server.on('close', function() { console.log('server closed!'); });<strong> </strong></span> |
Handling Errors
When handling a socket on the client or the server you can (and should) handle errors by listening to
the error event like this:
1 2 3 4 5 6 |
<span style="font-size: 20px"><span style="font-size: 14px">require('net').createServer(function(socket) {</span> <span style="font-size: 14px">socket.on('error', function(error) {</span> <span style="font-size: 14px">// do something</span> <span style="font-size: 14px">});</span> <span style="font-size: 14px">});</span><strong> </strong></span> |
If you fail to catch an error, Node will handle an uncaught exception and terminate the current process.
1 2 3 4 5 |
<span style="font-size: 14px"><strong>NOTE</strong> You can choose to catch uncaught exceptions — preventing your Node</span> <span style="font-size: 14px">process from being terminated — by doing something like this:</span> process.on('uncaughtException', function(err) { // do something }); |
BUILDING A SIMPLE TCP CHAT SERVER
1 2 3 4 5 6 7 8 9 10 |
<span style="font-size: 14px"><strong>The TCP chat server — step 1</strong></span> <span style="font-size: 12px">var net = require('net');</span> <span style="font-size: 12px">var server = net.createServer();</span> <span style="font-size: 12px">server.on('error', function(err) {</span> <span style="font-size: 12px">console.log('Server error:', err.message);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('close', function() {</span> <span style="font-size: 12px">console.log('Server closed');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.listen(4000);</span> |
Accepting Connections
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<span style="font-size: 14px"><strong>The TCP chat server — step 2</strong> <span style="font-size: 12px">var net = require('net'); var server = net.createServer(); <strong>server.on('connection', function(socket) { // accept new client connections</strong> <strong>console.log('got a new connection');</strong> <strong>});</strong> server.on('error', function(err) { console.log('Server error:', err.message); }); server.on('close', function() { console.log('Server closed'); }); server.listen(4000);</span> </span> |
Reading Data from a Connection
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<span style="font-size: 16px"><strong>The TCP chat server — step 3</strong></span>. <span style="font-size: 12px">var net = require('net');</span> <span style="font-size: 12px">var server = net.createServer();</span> <span style="font-size: 12px">server.on('connection', function(socket) {</span> <span style="font-size: 12px">console.log('got a new connection');</span> <span style="font-size: 12px"><strong>socket.on('data', function(data) { // for the incoming data by binding to the data event</strong></span> <span style="font-size: 12px"><strong>console.log('got data:', data);</strong></span> <span style="font-size: 12px"><strong>});</strong></span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('error', function(err) {</span> <span style="font-size: 12px">console.log('Server error:', err.message);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('close', function() {</span> <span style="font-size: 12px">console.log('Server closed');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.listen(4000);</span> |
Collecting All the Clients
Creating a chat server in which you have to broadcast the user data to everyone
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<span style="font-size: 16px"><strong>The TCP chat server — step 4</strong></span> <span style="font-size: 12px">var net = require('net');</span> <span style="font-size: 12px">var server = net.createServer();</span> <span style="font-size: 12px"><strong>var sockets = [];</strong></span> <span style="font-size: 12px">server.on('connection', function(socket) {</span> <span style="font-size: 12px">console.log('got a new connection');</span> <span style="font-size: 12px"><strong>sockets.push(socket);</strong></span> <span style="font-size: 12px">socket.on('data', function(data) {</span> <span style="font-size: 12px">console.log('got data:', data);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('error', function(err) {</span> <span style="font-size: 12px">console.log('Server error:', err.message);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('close', function() {</span> <span style="font-size: 12px">console.log('Server closed');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.listen(4000);</span> |
Broadcasting Data
Every time a connected user types anything, you need to send it to every other connected user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<span style="font-size: 16px">The TCP chat server — step 5</span> <span style="font-size: 12px">var net = require('net');</span> <span style="font-size: 12px">var server = net.createServer();</span> <span style="font-size: 12px">var sockets = [];</span> <span style="font-size: 12px">server.on('connection', function(socket) {</span> <span style="font-size: 12px">console.log('got a new connection');</span> <span style="font-size: 12px">sockets.push(socket);</span> <span style="font-size: 12px">socket.on('data', function(data) {</span> <span style="font-size: 12px">console.log('got data:', data);</span> <span style="font-size: 12px"><strong>sockets.forEach(function(otherSocket) {</strong></span> <span style="font-size: 12px"><strong>if (otherSocket !== socket) {</strong></span> <span style="font-size: 12px"><strong>otherSocket.write(data); }</strong></span> <span style="font-size: 12px"><strong>});</strong></span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('error', function(err) {</span> <span style="font-size: 12px">console.log('Server error:', err.message);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('close', function() {</span> <span style="font-size: 12px">console.log('Server closed');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.listen(4000);</span> |
Removing Closed Connections
We have to remove the connection when it gets closed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
<span style="font-size: 14px"><strong>Simple TCP chat server.</strong></span> <span style="font-size: 12px">var net = require('net');</span> <span style="font-size: 12px">var server = net.createServer();</span> <span style="font-size: 12px">var sockets = [];</span> <span style="font-size: 12px">server.on('connection', function(socket) {</span> <span style="font-size: 12px">console.log('got a new connection');</span> <span style="font-size: 12px">sockets.push(socket);</span> <span style="font-size: 12px">socket.on('data', function(data) {</span> <span style="font-size: 12px">console.log('got data:', data);</span> <span style="font-size: 12px">sockets.forEach(function(otherSocket) {</span> <span style="font-size: 12px">if (otherSocket !== socket) {</span> <span style="font-size: 12px">otherSocket.write(data);</span> <span style="font-size: 12px">}</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px"><strong>socket.on('close', function() {</strong></span> <span style="font-size: 12px"><strong>console.log('connection closed');</strong></span> <span style="font-size: 12px"><strong>var index = sockets.indexOf(socket);</strong></span> <span style="font-size: 12px"><strong>sockets.splice(index, 1);</strong></span> <span style="font-size: 12px"><strong>}); });</strong></span> <span style="font-size: 12px">server.on('error', function(err) {</span> <span style="font-size: 12px">console.log('Server error:', err.message);</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.on('close', function() {</span> <span style="font-size: 12px">console.log('Server closed');</span> <span style="font-size: 12px">});</span> <span style="font-size: 12px">server.listen(4000);</span> |
Use Your TCP Chat Server
Now you should be ready to test your server. You can save the fi e to chat_server.js and launch it
through the command line:
$ node chat_server.js
You can now connect to that server using nc or telnet :
$ nc localhost 4000
If you can, try launching several of these in separate terminal windows. You can then see the chat
server in action.
Recent Comments