XSockets.NET TeamBlog

News, updates and other information from Team XSockets.NET

Here Team XSockets provide the latest information about the framework.
You will also find videos and stuff produced by us (and others).

If you have done something with XSockets.NET, tell us and we might post about it here!

 

The importance of state in realtime platforms

Wednesday, March 19, 2014 9:13 AM 0

Having state is crucial in real-time platforms. State is what helps us knowing what clients to send to (the subscribers), and state will also help us finding/sending-to a subset of subscribers...

Why is this important?

First of all we should NEVER broadcast data... A client that is not subscribing for a topic should never get a message about it. Second. If you have 1000 subscribers, but you only want to target 5 of them you have to be able to do so. The other 995 clients should NOT get the message and it should be EASY for you to find these 5 client as a subset from the 1000 subscribers.

An example...

Lets say that you have a chat (yeah I know it's always a chat). You have a lot of clients in the chat so you have to filter where to send the messages. To keep things simple we only have Name, City, Status and Hobby as criterias in the chat. So that the client can say "I'm James. A single person in Boston and my hobby is JavaScript".

We will now know the city, status and hobby of all the clients. What you do with this knowledge is up to you, but lets say that we want to send a message to all people having the same profile as the sender. What would that look like?

The controller

public class MyChat : XSocketController
{
    public string Name { get; set; }
    public string City { get; set; }
    public string Status { get; set; }
    public string Hobby { get; set; }

public void OnChatMessage(string message)
    {
        //This is all it takes to target the clients!
        this.SendTo(p => p.City == this.City && p.Status == this.Status && p.Hobby == this.Hobby
        , this.Name + " - " + message, "onChatMessage");
    }
    //Explanation:
    //Above e use the extension SendTo(Func<T,bool>, object o, string topic);
    //First parameters let you filter with intellisense
    //Second is the object to send (anything that can be serialized)
    //Third is the topic (subscription)
}

Thats it... And it is easy to set the properties on the controller from javascript if you do not want to pass them in with the connection (or write a method that handles the get/set stuff).

Bulding a UI for the MyChat controller could in its simplest form look something like:

The everybody is named 'Glen' chat

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title></title>
    </head>
    <body>
        <h3>The everybody is named 'Glen' chat</h3>
        <select id="cities">
            <option value="New York">New York</option>
            <option value="Boston">Boston</option>
            <option value="Phoenix">Phoenix</option>
        </select><hr />
        <select id="status">
            <option value="Single">Single</option>
            <option value="Relationship">Relationship</option>
        </select><hr />
        <select id="hobby">
            <option value="JavaScript">JavaScript</option>
            <option value="CSharp">CSharp</option>
        </select><hr />
        <input type="text" id="input-message" value="Goo LR" />
        <button id="btn-send">send</button>
        <div id="messages"></div>
    <script src="Scripts/jquery-2.0.3.js"></script>
    <script src="Scripts/XSockets.latest.js"></script>

<script>
        var conn = null;
        $(function () {
            //Create a connection
            conn = new XSockets.WebSocket('ws://localhost:4502/MyChat');
conn.onopen = function () {
                //Connected, set the C# properties (faking for demo purpose)
                conn.publish('set_City', { value: 'New York' });
                conn.publish('set_Hobby', { value: 'JavaScript' });
                conn.publish('set_Status', { value: 'Single' });
                conn.publish('set_Name', { value: 'Glen' });
//Subscribe for onchatmessage, but I will only get messages within the same city, hobby & status
                conn.on('onchatmessage', function (d) {
                    $('#messages').prepend($('<div>').text(d));
                });
            };
//When the button is clicked
            $('#btn-send').on('click', function () {
                conn.publish('onchatmessage', { message: $('#input-message').val() });
            });
            //When city is changed
            $('#cities').on('change', function () {
                conn.publish('set_City', { value: $(this).val() });
            });
            //When status is changed
            $('#status').on('change', function () {
                conn.publish('set_Status', { value: $(this).val() });
            });
            //When hobby is changed
            $('#hobby').on('change', function () {
                conn.publish('set_Hobby', { value: $(this).val() });
            });
        });
    </script>
    </body>
</html>

Custom Protocols in XSockets.NET

Sunday, February 09, 2014 2:50 PM 2

To follow this sample you have to use XSockets 3.0.4 +

One of many unique features in XSockets is how easy it is to add custom protocols. Since the protocols (as most things in XSockets) is a plugin you can add them by just creating a class.

The cool part is that XSockets supports cross-protocol communication. That means that if you connect for example a Arduino that talks a very simple protocol it will still be able to communicate with clients connected to for example RFC6455 (the websocket protocol).

This is huge strength since you within minutes can connect devices/things to participate in full duplex real-time communication.

Why are custom protocols & cross protocol communication important? WebSockets is not the only transport for real-time communication. You might wanna connect devices/things that do not have the capability to talk RFC6455. It may be a micro-controller or a raw socket client. Neither way you do not want to reinvent the wheel. You might also wanna implement your custom subprotocol such as http://wamp.ws/ and use that instead of our default RFC6455 protocol. The choice is yours!

Doing it from scratch

We will install XSockets into a console application and then add a web-application and create a very simple chat. Then we will create a custom (very simple) protocol so that we can connect from Putty and have a real-time chat between putty and the browser.

Step 1

Create a new ConsoleApplication and name it MyRealTimeServer, then open up the package manager console and install XSockets by typing Install-Package XSockets and hit enter.

When the package is installed you will see some sample code. paste that in the main method of the program.

using (var server = XSockets.Plugin.Framework.Composable.GetExport<IXSocketServerContainer>())
{
    server.StartServers();
    Console.WriteLine("Started, hit enter to quit");
    Console.ReadLine();
    server.StopServers();
}

You now have a real-time server, lets use it :)

Step2

Add another project, this time choose a web-project. I will use MVC but it really does not matter since we only will be writing javascript in it.

When the project is created open up the package manager console and install XSockets JavaScript API by typing Install-Package XSockets.JsApi and hit enter.

The install jQuery by typing Install-Package jQuery and hit enter.

Step 3

Add a new html file, I will call it index.html.

Then just paste in the simple chat you see below.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script src="Scripts/jquery-2.1.0.js"></script>
    <script src="Scripts/XSockets.latest.js"></script>
</head>
<body>
    <div id="chat">
        <input type="text" id="message" placeholder="hit enter to send..."/>
    </div>
    <div id="messages">
        
    </div>
    <script>
        var conn = null;
        $(function() {
            conn = new XSockets.WebSocket('ws://127.0.0.1:4502/Generic');
            conn.onopen = function () {
                //Subscribe to 'onmessage'
                conn.on('onmessage', function(data) {
                    $('#messages').prepend($('<div>').text(data));
                });
            };
            //When enter is hit, send text..
            $('#message').on('keydown', function(e) {                
                if (e.keyCode == 13) {
                    var text = $(this).val();
                    if (text.length == 0) return;
                    conn.publish('onmessage', text);
                    $(this).val('').focus();
                }
            });
        });
    </script>
</body>
</html>

Step 4

If you start the console application and then the web you will not have a very simple chat!

But we want to include Putty in the chat! So download Putty if you do not have it installed.

Step 5

We need the custom protocol to be able to connect putty, since putty does not use RFC6455 (websocketsprotocol).

In the console application choose "add new item" and navigate to the XSockets templates (installed when xsockets was installed). Name the class "TextProtocol"

Step 6

We now have a protocol, but this will expect JSON since that is the default behaviour of the base protocol. So we have to override the methods for incoming and outgoing data and tranforms/parse the data.

We also have to take care of publish/subscribe since the putty client want to subscribe to the "onmessage" event.

So... We just override the two methods OnIncomingTextFrame and OnOutgoingTextFrame

 

public override ITextArgs OnIncomingTextFrame(List<byte> payload)
{
    var data = Encoding.UTF8.GetString(payload.ToArray()).Replace("\r\n", string.Empty);
    if (data.Length == 0) return null;
    ITextArgs ta;
    if (data.Contains(":"))
    {
        ta = ConvertToTextArgs(data);
    }
    else
    {
        ta = new TextArgs(data, "OnMessage");
    }
    return ta;
}
private ITextArgs ConvertToTextArgs(string s)
{
    var topic = s.Split(':')[0].ToLower().Trim();
    var content = s.Split(':')[1];
    if (topic == "subscribe")
    {
        return GetPubSub(content, Constants.Events.PubSub.Subscribe);
    }
    if (topic == "unsubscribe")
    {
        return GetPubSub(content, Constants.Events.PubSub.Unsubscribe);
    }
    return new TextArgs(content, topic);
}
private ITextArgs GetPubSub(string topic, string pubsub)
{
    var subscription = new XSubscriptions {Event = topic};
    var json = this.Controller.JsonSerializer.SerializeToString(subscription);
    return new TextArgs(json, pubsub);
}
public override byte[] OnOutgoingTextFrame(ITextArgs args)
{
    return Encoding.UTF8.GetBytes(args.@event + ":" + args.data + "\r\n");
}

We are done.. Try it out

So start the console application again and open up the browsers again...

Then open putty, and type in the ip and port of the XSockets server. Remember to use RAW

To connect to our protocol we send the controller to connect to as well as the protocol handshake.

We want to use the Generic controller and the handshake is very simple in our demo protocol... So just type"Generic TextProtocol" and hit enter.

If everything is ok XSockets will return the HostResponse.

Now send in "subscribe:onmessage" to subscribe to messages in the chat.

Now just send messages between putty and the browser :)

Note: There are obviously stuff missing, such as security masking data etc. But it shows that you can connect anything very easy with xsockets and use the power of publish/subscribe between clients with different capabilities!

Hopefully you realize the power and possibilities in this!

Now create something awesome and tell us about it :)

Regards

Uffe, Team XSockets.NET

 

XSocketsControllerBase<t> enables real-time controllers

Thursday, January 16, 2014 11:57 AM 5

In version 3.0.3 we introduce a new set of features that enables you to run XSockets.NET on Internet Information Server 8+ . By just installing the new Nuget package XSockets.MVC onto your ASP.NET MVC 4.5 project enables you to host and run "Realtime ASP.NET MVC Controllers" . This simplifies deployment of XSockets.NET powered solutions to (ISP's) target platforms (environments)  where you cant setup and customize firewall rules and/or install our recomended Windows Service. 

This blog post gives you a brief description of how it works.

First of all you will need to install the following packages on  your project by using the package-manager (Nuget)

PM> Install-Package XSockets.MVC
PM> Install-Package XSockets.JsAPI 


Register your plugins and initialize the XSockets.NET via global.asax

...
protected void Application_Start()
        {
            container = Composable.GetExport<IXSocketsRelayContainer>();
            container.Start();
            AreaRegistration.RegisterAllAreas();
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }        

You can now communicate with XSockets.NET from "native" Windows WebSockets (IIS8/Windows 2012 Server) and take advantahe of most of the features found in XSockets.NET

XSocketsController

    
    //The RealTime controller of XSockets.NET
    public class Chat : XSocketController
    {
        public string Nickname { get; set; }
        
        public void ChatMessage(string text)
        {
            this.SendToAll(new {  text, date = DateTime.Now, nickName = this.Nickname },"onChatMessage");
        }
    }

ASP.NET MVC Controller

  //We inherit the XSocketsControllerBase and specify the XSocketsController that will keep state in our MVC controller
    public class ChatController : XSocketsControllerBase<Chat>
    {
        // Just return the View (client)
        public ViewResult Index()
        {
            return View();
        }
    }

ASP.NET MVC View (Razor)

@{
    ViewBag.Title = "Index";
}
 
<h2>This is the RazorView for the RealtimeMVC Controller - XSocketsControllerBase<ChatController> </h2>
 
<p>This is a realtime ASP.NET MVC Controller</p>
 
<div>
    <input /><span></span>
</div>
<div id="messages"></div>
 
<script>
    var ws;
    $(function () {
        ws = new XSockets.WebSocket("ws://localhost:8860/ChatController");
 
        ws.on(XSockets.Events.open, function (connection) {
            //Connected, just set a dummy Nickname on our ChatController
            ws.publish("set_Nickname", { value: 'Sidney' });
            
            console.log("Connected to XSockets using native IIS WebSockets.", connection);
            
            //Listen for the 'onChatMessage' event and output the data to the DOM
            ws.on("onChatMessage", function (msg) {
                $("<p>").text(msg.text).prependTo("#messages");
            });
        });
        
        //When user hits enter send the message
        $("input").on("keydown", function (evt) {
            if (evt.keyCode === 13) {
                ws.publish("chatMessage", { text: $(this).val() });
                $(this).val('');
            }
        });
    });
</script>