5

I want to use linq to process events received via a websocket connection. This is what I have so far:

    private static void Main()
    {
        string WsEndpoint = "wss://push.planetside2.com/streaming?environment=ps2&service-id=s:quicktesting";
        using (WebSocket ws = new WebSocket(WsEndpoint))
        {
            ws.OnMessage += Ws_OnMessage;

            ws.Connect();
            Console.ReadKey();
            ws.Close();
        }
    }

    private static void Ws_OnMessage(object sender, MessageEventArgs e)
    {
        Console.WriteLine(e.Data);
    }

The first think that stumps me is how to turn ws.OnMessage into some sort of event stream. I cannot find any examples online for observing an external event source with reactive extensions. I intend to parse the messages into json objects, then filter and aggregate them.

Could someone provide an example of creating an observable from the websocket messages, and subscribing to it?


Edit: Final Working Code

The only difference from the chosen answer is that I initialized the websocket before passing it into Observable.Using

//-------------------------------------------------------
// Create websocket connection
//-------------------------------------------------------
const string wsEndpoint = "wss://push.planetside2.com/streaming?environment=ps2&service-id=s:quicktesting";
WebSocket socket = new WebSocket(wsEndpoint);


//-------------------------------------------------------
// Create an observable by wrapping ws.OnMessage
//-------------------------------------------------------
var globalEventStream = Observable
    .Using(
        () => socket,
        ws =>
            Observable
                .FromEventPattern<EventHandler<MessageEventArgs>, MessageEventArgs>(
                    handler => ws.OnMessage += handler,
                    handler => ws.OnMessage -= handler));
//---------------------------------------------------------
// Subscribe to globalEventStream
//---------------------------------------------------------

IDisposable subscription = globalEventStream.Subscribe(ep =>
{
    Console.WriteLine("Event Recieved");
    Console.WriteLine(ep.EventArgs.Data);
});

//----------------------------------------------------------
// Send message over websocket
//----------------------------------------------------------
socket.Connect();
socket.Send("test message");
// When finished, close the connection.
socket.Close();
mooglinux
  • 815
  • 1
  • 11
  • 27

1 Answers1

8

You should set up your observable like this:

    var observable =
        Observable
            .Using(
                () => new WebSocket(WsEndpoint),
                ws =>
                    Observable
                        .FromEventPattern<EventHandler<MessageEventArgs>, MessageEventArgs>(
                            handler => ws.OnMessage += handler,
                            handler => ws.OnMessage -= handler));

This will correctly create the socket and then observe the event when the observable is subscribed to. When the subscription is disposed it will correctly detach from the event and dispose of the socket.


The type of observable will be IObservable<EventPattern<MessageEventArgs>>. You consume this observable in this way:

IDisposable subscription = observable.Subscribe(ep =>
{
    Console.WriteLine(ep.EventArgs.Data);
});

Thanks for posted the NuGet reference.

Here's the working code:

const string WsEndpoint = "wss://push.planetside2.com/streaming?environment=ps2&service-id=s:quicktesting";

Console.WriteLine("Defining Observable:");

IObservable<EventPattern<WebSocketSharp.MessageEventArgs>> observable =
    Observable
        .Using(
            () =>
            {
                var ws = new WebSocketSharp.WebSocket(WsEndpoint);
                ws.Connect();
                return ws;
            },
            ws =>
                Observable
                    .FromEventPattern<EventHandler<WebSocketSharp.MessageEventArgs>, WebSocketSharp.MessageEventArgs>(
                        handler => ws.OnMessage += handler,
                        handler => ws.OnMessage -= handler));

Console.WriteLine("Subscribing to Observable:");

IDisposable subscription = observable.Subscribe(ep =>
{
    Console.WriteLine("Event Recieved");
    Console.WriteLine(ep.EventArgs.Data);
});

Console.WriteLine("Writing to Source:");

using (var source = new WebSocketSharp.WebSocket(WsEndpoint))
{
    source.Connect();
    source.Send("test");
}
Enigmativity
  • 113,464
  • 11
  • 89
  • 172
  • What is the benefit to putting the websocket inside `Observable.Using` as opposed to the other answer? – mooglinux Aug 24 '16 at 04:33
  • 3
    When you dispose the observable's subscription, the socket gets disposed as well. – Shlomo Aug 24 '16 at 05:37
  • Do I write a custom function for `handler`? If so, what is the return type? I attempted to change `handler` to a function that printed the data and returned `void`, but that did not work. – mooglinux Aug 25 '16 at 21:58
  • @mooglinux - There is no need to change `handler` - in fact, if you do you are likely to break the code. I've added to the answer how to consume the observable. – Enigmativity Aug 26 '16 at 00:15
  • Still not working. =/ I checked and my original version is still working, so it isn't a network issue. Will update my question with what I have now. – mooglinux Aug 26 '16 at 00:43
  • @mooglinux - I've tried to download WebSockets# to be able to actually run the code, but, even though I found it on NuGet, I can't find the exact library for the code you've presented. Can you tell me where to get it from? – Enigmativity Aug 26 '16 at 05:53
  • Its a pre-release version, still on Nuget: 1.0.3-rc11 – mooglinux Aug 26 '16 at 13:44
  • @mooglinux - Can you please let me know the NuGet id? – Enigmativity Aug 27 '16 at 02:25
  • @Enigmativity Made one change, to allow me to send messages over the socket as well, and added to my post. THANK YOU for all the help! – mooglinux Sep 02 '16 at 05:23