Node.Js : As A WebSocket Relay And Possible Filter

I was At work the other day and my boss was pushing (nicely) my team lead and I to create a XMAS present for him. What we basically wanted was to capture certain information about certain event that were occurring in the system in real time and have them sent to a web site. I have done something like this in the past using Duplex WCF and MSMQ and SignalR.

This time I thought I just can’t be bother to write all that plumbing and thought about it, and I decided we could go with a simple node.js server, that would serve up a static html page. The static html page would use the node.js and one of the awesome node.js packages namely socket.io. I am fully aware of the awesome Fleck WebSocket library, that does indeed allow you to send data from a .NET client directly to a static HTML page using the Fleck WebSocket API.

Thing is we wanted to filter out certain things, which was not really achievable using Fleck, and it is something that socket.io does very well, so we went with socket.io. I am now going to show you the code, it should however be noted that the code below doesn’t include any filtering, but that is possible using socket.io, where you can broadcast, only send to certain client, send a private message and so on, it really is very good.

So what does the code do again, well it allows a .NET Client to send data via a WebSocket to a node.js server, where it is read and pumped out to a static HTML page using  socket.io. Here is the entire code for the .NET client

public class DemoMessage
{
    public int Type { get; set; }
    public string Description { get; set; }

    public DemoMessage(int type, string description)
    {
        this.Type = type;
        this.Description = description;
    }

    public DemoMessage()
    {

    }
}

class Program
{
    internal static DataContractJsonSerializer jss;

    public async void Run()
    {
        int messageId = 1;
        bool shouldRun = true;
        string exitCode = "Q";

        try
        {
            while (shouldRun)
            {
                Console.WriteLine("Enter you new message value");
                string dataEntered = Console.ReadLine();

                if (dataEntered.Equals(exitCode, StringComparison.CurrentCultureIgnoreCase))
                {
                    shouldRun = false;
                }
                else
                {
                    WebClient client = new WebClient();
                    NameValueCollection values = new NameValueCollection();
                    DemoMessage mess = new DemoMessage(messageId++, dataEntered);
                    AddValue(values, "DemoMessage", mess);
                    Console.WriteLine("Uploading values");
                    client.UploadValuesAsync(new Uri("http://localhost:3000/MessageReceive"), values);
                }
            }

        }
        catch (Exception ex)
        {
        }
    }

    static void Main(string[] args)
    {
        new Program().Run();
    }

    internal static T GetValue(Byte[] results) where T : class
    {
        using (MemoryStream ms = new MemoryStream(results))
        {
            jss = new DataContractJsonSerializer(typeof(T));
            return (T)jss.ReadObject(ms);
        }
    }

    internal static void AddValue(NameValueCollection values, string key, object value)
    {
        jss = new DataContractJsonSerializer(value.GetType());
        using (MemoryStream ms = new MemoryStream())
        {
            jss.WriteObject(ms, value);
            string json = Encoding.UTF8.GetString(ms.ToArray());
            values.Add(key, json);
        }
    }
}

And now onto the node setup. I am using node with Express, and full instructions can be found in the node codes README.txt (though if you download attached code you won’t need to do anything other than install node.js) The node.js application

var express = require('express');
var mess = require('./routes/messageReceive');

var http = require('http');
var path = require('path');
var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
//app.set('views', __dirname + '/views');
//app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

var server = http.createServer(app);
var io = require('socket.io').listen(server);

app.post('/MessageReceive', function (req, res) {
	mess.ReceivePost(req, res, io);
});

server.listen(app.get('port'), function(){
    console.log("Express server listening on port " + app.get('port'));
});

It can be seen from this that there the "Static" content csn be served from the "public folder", and there is a single route which accepts the POST data, called "MessageReceive"

exports.ReceivePost = function (req, res, io) {

    console.log('RAW body' + req.body);

     var requestJsonString = JSON.stringify(req.body);
     console.log('STRINGIFIED body' + requestJsonString);

     var requestJson = JSON.parse(requestJsonString);
     console.log('requestJson :' + requestJson);

     var messageJson = JSON.parse(requestJson['DemoMessage']);
     console.log('messageJson " ' + messageJson);

	 console.log('Message Seen');
	 console.log('Type was :' + messageJson.Type);
	 console.log('Description was :' + messageJson.Description);

     io.sockets.emit('newMessage',
         {
             type: messageJson.Type,
             description: messageJson.Description
         });
     res.write('ok');
};

So this code takes the request (from .NET code) and sends it out on the WebSocket. The last peice of the puzzle is the static HTML page that will be the client end of the WebSocket. Lets look at that next. Which is shown below

$(document).ready(function () {

	var socket = io.connect('http://localhost');
	socket.on('newMessage', onNewMessage);
	alert('In the Demo page');
});

function onNewMessage(data) {
    console.log('onNewMessage');
    console.log(data);
	alert('message description ' + data.description + ' message type ' + data.type);
}

All you need to do it run the node command line, change to the directory where you have the node code, type "code app.js" and then launch a browser and point it to http://localhost:3000/demopage.html and then run the .NET code, and send some messages, you should see the static HTML alert your typed .NET messages. Enjoy As usual here is a small demo app : NodeRelay.zip

Advertisements

3 thoughts on “Node.Js : As A WebSocket Relay And Possible Filter

  1. anas says:

    Hye Sasha.

    Could you reupload the demoApp please?

    thanks

    • sachabarber says:

      Ah I think I may have lost that dropbox content. Ooops

    • sachabarber says:

      Actually the link works fine, you might have dropbox blocked by work / proxy, link downloads just fine I just tried at home

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: