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!

 

unsigned vs signed assemblies, happy to not care!

Friday, April 25, 2014 9:45 AM 0

The topic “signed vs unsigned assemblies” has become a hot topic in the .NET community, and today I saw a tweet where Itamar Syn-Hershko (@synhershko) said:

I’ve had enough. I’m moving to removing strong-naming aka signed assemblies from #Lucene.net http://permalink.gmane.org/gmane.comp.jakarta.lucene.net.devel/6615 #dotnet

So I read the post, and I actually don not have a opinion about “Strongly Named Assemblies”… That might seem strange since it seems to be a hot topic. Guessing that it is a hot topic since peoples (developers) are having trouble with it (doh).

So why don´t I have any opinion about this?
Because I do not have a problem with assemblies (signed or not).

I spend most of my time as a developer on the XSockets.NET team, and almost all our assemblies are signed. But we use ServiceStack.Text (which is awesome by the way) that is unsigned! How?

 

Using unsigned assemblies in signed assemblies

You cant reference an unsigned assembly in signed assembly, but how can we use unsigned assemblies all over XSockets.NET even though XSockets.NET is signed?

Let us look at how we use the unsigned ServiceStack.Text inside of the signed XSockets.NET.

Have the interface in a signed assembly

Inside of the signed assembly XSockets.Core.Common.dll there is a interface for serialization.

using System;
using System.Collections.Generic;
using XSockets.Plugin.Framework;
using XSockets.Plugin.Framework.Attributes;
namespace XSockets.Core.Common.Utility.Serialization
{
    //Will export this interface... This is optional, can done at runtime.
    //but it will be replaced if another implementation is found
    [Export(typeof(IXSocketJsonSerializer), null, Rewritable.Yes)]
    public interface IXSocketJsonSerializer
    {
        //Serialization
        string SerializeToString<T>(T obj);
        string SerializeToString(object obj, Type type);
        //Deserialization
        T DeserializeFromString<T>(string json);
        object DeserializeFromString(string json, Type type);
        IDictionary<string, string> DeserializeFromString(string json, params string[] keys);
    }    
}

Have the implementation in a unsigned assembly

Inside of the unsigned assembly XSockets.Serialization.dll we have a reference to ServiceStack.Text and we implement the interface found in the signed assembly XSockets.Core.Common.dll (described above)

using System;
using System.Collections.Generic;
using System.Linq;
using ServiceStack.Text;
using XSockets.Core.Common.Utility.Serialization;
namespace XSockets.Serialization
{
    /// <summary>
    /// The default plugin for serialization
    /// To have your custom serializer implement IXSocketJsonSerializer
    /// </summary>    
    public class XSocketJsonSerializer : IXSocketJsonSerializer
    {
        public XSocketJsonSerializer()
        {
            JsConfig.ExcludeTypeInfo = true;
        }
        public string SerializeToString<T>(T obj)
        {
            return JsonSerializer.SerializeToString(obj);            
        }
        public string SerializeToString(object obj, Type type)
        {
            return JsonSerializer.SerializeToString(obj, type);
        }
        public T DeserializeFromString<T>(string json)
        {
            return JsonSerializer.DeserializeFromString<T>(json);
        }
        public object DeserializeFromString(string json, Type type)
        {           
            return JsonSerializer.DeserializeFromString(json, type);
        }
        public IDictionary<string,string> DeserializeFromString(string json, params string[] keys)
        {
            var obj = JsonSerializer.DeserializeFromString<List<JsonObject>>(@json);
            return keys.ToDictionary(key => key, key => obj[0].Child(key));
        }
    }    
}

Have the usaged in a signed assembly

So we had an interface in a signed assembly, the implementation in a unsigned assembly since we wanted to use ServiceStack.Text (unsigned). Now we need to get the instance in a signed assembly.

The XSockets.Plugin.Framework will help us…
There are several ways of getting an instance of the JsonSerializer.

  1. Get the instance from the plugin framework directly.

    var serializer = Composable.GetExport<IXSocketJsonSerializer>();
    
    
  2. Mark a property with the [ImportOne] attribute and it will be created when the parent is created.

    [ImportOne(typeof(IXSocketJsonSerializer))]
    public IXSocketJsonSerializer JsonSerializer { get; set; }
    
    

Summary

I find the recent discussions about this topic in social media to be very interesting, but it feels great to not have to bother about it. In the best of worlds all assemblies would be either signed or unsigned.

The way we do it probably don’t fit all project since it demands full modularity, but hopefully it will help (or provide an ideas) to someone reading it.

If you are interested in learning more about the plugin framework here is some info

EDIT: When I think about it I would not mind switching XSockets to unsigned since I actually do not care about signing the assemblies, but I guess that some users of XSockets would get upset since they probably sign their assemblies.

Regards
Uffe, Team XSockets

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