Writing A Daytime Server In Node.js

I’ve previously written about using node.js as a simple UDP listener, now I thought I’d expand on this and give an example of a node.js application that works as both a UDP and TCP server.

A simple service that offers both UDP and TCP connections would be the Daytime Protocol, as defined in RFC 867. It listens to port 13 for both TCP and UDP connections, and returns the current date and time. Your local computer may well have this function enabled, to test the TCP version, you can simply telnet to port 13 and see what is returned.

telnet localhost 13

If you find you don’t have a local Daytime service running, try calling the one at time.ien.it, you should see something like this…

$ telnet time.ien.it 13
Trying 193.204.114.105...
Connected to ntp.ien.it.
Escape character is '^]'.
12 APR 2011 18:51:11 CEST
Connection closed by foreign host.

As you can see it simply returns the date and time before closing the connection.

We could write something like this very easily in node.js. In this case we’ll return the date in JavaScript’s UTC string format instead to keep it simple.

var net = require('net');
var port = 1300;
var now = function() {
  var date = new Date();
  return new Buffer(date.toUTCString() + "rn");
};
var tcpserver = net.createServer(function(c) {
  c.write(now());
  c.end();
});
tcpserver.listen(port);

We can test this by telneting to localhost on port 13

$ telnet localhost 1300
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Tue, 12 Apr 2011 17:17:55 GMT
Connection closed by foreign host.

Let’s take a quick detour into what the code is doing if you’ve not used node.js for any network programming before.

We require('net') so we can use node.js’s network socket support.

The now() function simply returns a Buffer with the current UTC date and time string in. A Buffer in node.js refers to the raw memory used behind the data, in this case our string with the date and time in.

Finally, we create the server, and add a callback function that is called when something connects to the socket. In this case we’re just writing out the contents of the now() function and ending the connection. Last but not least, we tell the socket which port to listen on.

We can see that this code works, but the Daytime protocol also offers a UDP service on the same port that can return the date and time string to a client.

Let’s add in some code to support this. We’ll assume our now() function and port variable are available already.

var dgram = require('dgram');
var udpserver = dgram.createSocket("udp4", function(msg, rinfo) {
  var daytime = now();
  udpserver.send(daytime, 0, daytime.length, rinfo.port, rinfo.address);
});
udpserver.bind(port);

So what is going on here? Well like the TCP code, we have to require('dgram'); to have access to node.js’s UDP support.

Next we create the socket and create a callback function that returns the date and time string back to the IP address and port of the calling computer. Finally we bind this to the port so we start listening for messages.

It’s harder to test a UDP server as we can’t telnet in, we will have to write a simple UDP client to send a blank message to the server and print out any replies to the console.

var dgram = require('dgram');
var message = new Buffer(" ");
var server_ip = '127.0.0.1';
var server_port = 43278;
var client = dgram.createSocket("udp4");
client.on('message', function (msg) {
  console.log(msg.toString());
  client.close();
});
client.send(message, 0, message.length, server_port, server_ip);

When you run this client on the same machine as your server you should get back the current date and time.

Here’s the final code for our Daytime server.

var net = require('net');
var dgram = require('dgram');
var port = 1300;
var now = function() {
  var date = new Date();
  return new Buffer(date.toUTCString() + "rn");
}
var tcpserver = net.createServer(function(c) {
  c.write(now());
  c.end();
});
tcpserver.listen(port);
var udpserver = dgram.createSocket("udp4", function(msg, rinfo) {
  var daytime = now();
  udpserver.send(daytime, 0, daytime.length, rinfo.port, rinfo.address);
});
udpserver.bind(port);

Using PHP To Send A UDP Message

Previously I’ve written about sending UDP datagrams using Perl and JavaScript with node.js.

As I’ve been using a lot of PHP recently, I thought I’d show how to send data over UDP using PHP.

If you’ve not come across UDP before, it’s a simple protocol for sending messages over the internet that aren’t guaranteed to arrive. You just fire them off and hope they arrive.

The previous examples showed sending a simple heartbeat message, a string simply saying “PyHB”, to a server listening on port 43278. I’ll do the same in this example.

Firstly we’ll setup a few variables saying where we’ll be sending the the message to, along with how often we want to send the message and what it should say.

$server_ip = '127.0.0.1';
$server_port = 43278;
$beat_period = 5;
$message = 'PyHB';

Now we have to create the socket, using the socket_create function. We need the domain to be of type AF_INET as we are using an IP4 address for our server, the type needs to be SOCK_DGRAM and the protocol needs to be SOL_UDPas we’re sending a UDP datagram.

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP))

It’s time to send the message now, and to do this we can use PHP’s socket_sendto function. This function takes the parameters of the socket to send the message over, the message itself, the length of the message, some flags, the destination address of the message and the port to send it to. We’re not setting any flags so we can just set this field to 0. The following code will do the trick.

socket_sendto($socket, $message, strlen($message), 0, $server_ip, $server_port);

Let’s wrap this up in a loop that sends the message every $beat_period seconds.

<php
$server_ip   = '127.0.0.1';
$server_port = 43278;
$beat_period = 5;
$message     = 'PyHB';
print "Sending heartbeat to IP $server_ip, port $server_portn";
print "press Ctrl-C to stopn";
if ($socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP)) {
  while (1) {
    socket_sendto($socket, $message, strlen($message), 0, $server_ip, $server_port);
    print "Time: " . date("%r") . "n";
    sleep($beat_period);
  }
} else {
  print("can't create socketn");
}
?>

This code is run on the command line, and not via a web server.

Writing A UDP Server Using Node.js

Previously, I’ve written about using node.js to send a heartbeat to a python server using a UDP datagram.

Of course you may not want to run Python if you using node.js so I thought I’d give you a quick run through on writing a UDP server using node.js.

The earlier heartbeat example sent a small message saying “PyHB” to a server listening on port 43278. This example will listen out for that message and show it on the console to prove it’s working.

The first thing we need to do is to require("dgram") to allow us access to the dgram library.

var dgram = require("dgram");

We now need to create a datagram socket to listen on, as we’re going to listen out for an IP4 datagram we create this of type udp4.

var server = dgram.createSocket("udp4");

Node.js lets us bind to events, and dgram gives us three, message, listening and close.

To listen for an event, we need to use the listening event. As with other JavaScript events, we can pass in a callback function to actually do something when the event is fired. In this case, we’ll just use display the incoming message on the console, along with some details of the server that sent it.

server.on("message", function (msg, rinfo) {
  console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
});

It’s also useful to know we’ve actually setup our socket correctly, so we can use the listening event to return a message to console that everything has been setup OK and is working.

server.on("listening", function () {
  var address = server.address();
  console.log("server listening " + address.address + ":" + address.port);
});

Finally we need to actually bind our socket to a port so it can start listening for messages. For this we have to use the bind method.

server.bind(43278);

Putting this all together we have the following code that can listen for UDP datagrams and show them on the console.

var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
  console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port);
});
server.on("listening", function () {
  var address = server.address();
  console.log("server listening " + address.address + ":" + address.port);
});
server.bind(43278);

I hope this has been a useful quick introduction to writing a UDP server in node.js.