top of page

.NET Standard Simple HTTP Server: Websockets

Source:

https://github.com/Corey255A1/BareBonesHttpServer


Suggested Reading:

Previous Post: https://www.wundervisionenvisionthefuture.com/blog/net-standard-simple-http-server


https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers


Websockets allow for full duplex communication between a client and server. This is useful for realtime communication such as chats or a game like http://slither.io/


On the Javascript side, starting a Websocket is like this:

var ws = new WebSocket("ws://localhost/socket");


I'm not trying to be backwards compatible, I don't really care about old browsers. Everything is going to be forward looking.


The browser client then sends the server a WebSocket Upgrade request. This is just a plain HTTP Request that looks like this:


GET /chat HTTP/1.1

Host: wundervision

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==

Sec-WebSocket-Version: 13


In my demo code, I'm looking for the Sec-WebSocket-Key to determine if it is a websocket request.

The key step here is creating the Sec-WebSocket-Accept code. To do this, use the key in the Sec-WebSocket-Key field (in our example: dGhlIHNhbXBsZSBub25jZQ==) add to it the string 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 (See the Mozilla document about this magic string). Compute the SHA1 hash of the string, and convert that to a Base64 String.


So our result would be s3pPLMBiTxaQ9kYGzzhZRbK+xOo= (These keys were the demo from the Mozilla site)


After that I tell our client handler that it is now a websocket handler, and then some more packet processing fun occurs!


A Websocket frame has several bit fields and optional fields. The Mozilla page goes over them, and also here is the entire specification. https://tools.ietf.org/html/rfc6455


The WebSocketFrame (in the Websocket.cs) class handles the decoding and encoding of the frames.




One interesting note about the WebSocket frame is the XOR Masking of the data from the Client. All client data uses the Mask field, and in order to recover the original payload data, the data has to be iterated over and XOR with the MaskingKey. Data sent from the Server is typically not done this way.


Once the data is decoded, it is sent back up to the controlling application for handling and responding back with WebSocket data!


The most basic WebSocket in Javascript sends over string data on the click of a button.


On the server side, I just have it respond to the client with a This is a WebSocket server response!

And that's it! So far, this seems to get me everything I need to server basic webpages, and establish basic websocket support.

The best part is, I wrote it all in .NET Standard 2.0, which means in theory this can be used in all .NET variations. (At least that is how I understand it.)


Happy coding and let me know if you have questions or suggestions!


Comments


bottom of page