Search code examples
c#javascriptwebsocketxsockets.net

Message not recieved when sent from OnOpen event


I am using XSockets 3.x (latest).

I have set up a controller:

public class NotificationsController : XSocketController
{
    public NotificationsController()
    {
        // Bind an event for once the connection has been opened.
        this.OnOpen += OnConnectionOpened;

        // Bind an event for once the connection has been closed.
        this.OnClose += OnConnectionClosed;
    }

    void OnConnectionOpened(object sender, XSockets.Core.Common.Socket.Event.Arguments.OnClientConnectArgs e)
    {
        // Notify everyone of the new client.
        this.SendToAll(new TextArgs("New client. Called right from OnConnectionOpened.", "notify"));
    }
}

As can be seen, it's just a basic controller, listening for connections and informing everyone once a new connection is made, though, it doesn't work - the message is not recieved. Chrome's dev-tools show no Frame either.

My web-client:

var xs = new XSockets.WebSocket("ws://" + window.location.hostname + ":1338/notifications");

xs.onopen = function(e)
{
    console.log("Connected", e);
};

xs.on('notify', function(data)
{
    console.log(data);
});

I am presented with the following output in console:
Console output

And this in the Network tab -> Frames:
Network tab, Frames

I can fix the issue by deferring the SendToAll call to a System.Threading.Timer with some timeout. My debugging showed, that 50ms is not consistent, so I have set it up to 300ms and it seems to be working okay, but the timer feels very hacky.

How do I fix the problem?
Is there, maybe, an event I can listen to, when XSockets really is ready for the client?


Solution

  • The reason for this in 3.0.6 is that it is all about publish and subscribe.

    This means that a messages will only be sent to client with a subscription for the topic on the server. In the sample you have provided it looks like you have only one client. This client will not receive his own "notify" message since the binding

    xs.on("notify",callback);
    

    is not bound on the server when the OnOpen happens... So the client connecting will not get info about his own connection.

    There are several ways around this...

    1 Do not notify about the connection until you have bound the notify. This is done by adding a third callback to the binding. That callback will be triggered when the subscription is bound on the server. Like this

    xs.on('notify', function(d){console.log('a connection was established')}, function(){console.log('the server has confirmed the notify subscription')});
    

    You would call a servermethod inside the first callback to notify others...

    2 Do the binding on the server before sending the information, probably a smother option.

    void OnConnectionOpened(object sender, OnClientConnectArgs e)
    {
        //Add the subscription
        this.Subscribe(new XSubscriptions{Event = "notify",Alias = this.Alias});
        // Notify everyone of the new client.
        this.SendToAll("New client. Called right from OnConnectionOpened.", "notify");
    }
    

    3 Use XSockets.NET 4.0 BETA that has improved communication and allows RPC or Pub/Sub. In 4.0 you would do like this in teh OnOpen event

    //Send the message to all clients regardless of subscriptions or not...
    this.InvokeToAll("New client. Called right from OnConnectionOpened.", "notify");
    
    //Client side JavaScript
    xs.controller('NotificationsController').on('notify', function(data){
        console.log(data);
    });
    
    //Client side C#
    xs.Controller("NotificationsController").On<string>('notify', s => Console.WriteLine(s));
    

    4.0 has lots of other important improvements... You can read here is you are interested in 4.0 http://xsockets.github.io/XSockets.NET-4.0/

    //Can be typos in the samples... writing from the top of my head here...