Wednesday, September 11, 2013

WebSockets in .NET 4.5: System.Net.WebSockets.ClientWebSocket vs Windows.Networking.Sockets.MessageWebSocket

Props to this guy's example project on how to implement a simple WebSocket using System.Net.WebSockets in .NET 4.5. Another good example is here.

I am working on a Windows Store App (WinRT, Metro, Win 8, or whatever name they are trying to market this under currently) and a .NET 4.5 application. Both will be using a WebSocket to talk to the same server.

The WinRT Windows.Networking.Sockets.MessageWebSocket is a wonderfully simple way to use a WebSocket to send and receive strings back and forth. Microsoft has a nice sample project here.

The .NET 4.5 System.Net.WebSockets.ClientWebSocket is just the opposite. See aforementioned blog for a 'simple' example.

Please see both sample projects for details: MessageWebSocket, ClientWebSocket

Two things make the MessageWebSocket really easy to use. First, it has a messageRecieved event handler, so all you need to handle incoming messages is attach a method thusly:

messageWebSocket.MessageReceived += MessageReceived;

See the sample project for the MessageRecieved implementation.


ClientWebSocket requires wrapping the Send and Receive actions in tasks and monitoring the receive buffer with a loop. Reminds me of old time socket monitoring. I though WebSockets were supposed to make my life simpler?


Secondly, MessageWebSocket provides a DataWriter so all you have todo to read or write strings is set the message type, grab the reader, and send a string.


//set the message type
messageWebSocket.Control.MessageType = SocketMessageType.Utf8;
//wrap the output in a DataWriter
messageWriter = new DataWriter(messageWebSocket.OutputStream);
//put a string on the writer
messageWriter.WriteString(message);
// Send the data as one complete message.
await messageWriter.StoreAsync();



Compare this to the ClientWebSocket in .net 4.5:


byte[] sendBytes = Encoding.UTF8.GetBytes(message);
  var sendBuffer = new ArraySegment<byte>(sendBytes);
  await socket.SendAsync(
      sendBuffer,
      WebSocketMessageType.Text,
      endOfMessage: true,
      cancellationToken: cts.Token);



byte[] seriously? I already have a string why would I want to revert to such a low level wrapper?


Reading messages is similarly easy in MessageWebSocket vs ClientWebSocket. See the example projects for details.


Conclusion:


Its good to have all the options provided in the System.Net.WebSockets namespace, but the end of the day, a WebSocket should make my life easy when all I need to do is send and receive some strings (json for example). I find it vexing this is provided for Windows Store Apps, but they don’t provide the same thing across platforms.


If I iron this out I’ll try to get a sample project uploaded showing how to get behavior similar to MessageWebSocket while using ClientWebSocket. No timeframe on this, sorry.