Friday, 14 October 2011

The WebSockets offering for .NET 4.5 consists of several APIs that vary in granularity and purpose. The new System.Net.WebSockets namespace contains a set of types that are used regardless of whether you are hosting your WebSocket server in ASP.NET or if you are using the low level HttpListener class (WCF uses HttpListener when it needs to handle HTTP traffic in self-hosted mode). The goal of this set of types is to define a shared low-level WebSockets API that ASP.NET, WCF and .NET developers can build on top of.

System.Net.WebSockets is not to be confused with the new WinRT WebSocket APIs found in Windows.Networking.Sockets. The WinRT APIs provide client functionality only while the the System.Net.WebSockets types are designed for server side use.

The easiest way to get to know this new API is to look at a simple example. I’ve implemented a very basic WebSocket echo server in ASP.NET that demonstrates how to accept a WebSocket connection in ASP.NET, obtain an instance of System.Net.WebSockets.WebSocket and then begin send and receive operations using the methods on this type. Keep in mind that we do not expect most developers to use these low level APIs for every day applications – this is what our Microsoft.WebSockets NuGet package is for. Future posts will cover this package in more detail.

I’ve annotated the source code for this echo server and made it available in HTML format. Please check it out! Do you like samples presented in this style? Let me know in the comments.

If you want to download and run this example, it’s called AspNetWebSocketEcho and is part of my WebSocket Samples project on github. You will need to use the Windows 8 developer preview if you want to try this stuff out. See my earlier post for instructions on how to set up your development environment.

Yes you can use socket.io with IIS 7 via iisnode, but WebSockets won't work in this case. You can use socket.io and node on Windows without running in IIS (without iisnode) and then WebSockets will work.

Another alternative is to use SignalR (https://github.com/SignalR/SignalR). This means you can continue using ASP.NET and IIS. Once you then deploy your SignalR based app on a IIS 8.0 machine, WebSockets will become available. In the meantime, SignalR can use long polling, forever frames, server sent events, etc.

You would have to do additional work to allow socket.io to talk to your .NET websocket server because socket.io layers on top of various transports (including WebSockets) and defines its own protocol (https://github.com/LearnBoost/socket.io-spec).

If you instead used a pure WebSocket node client such as 'ws' (https://github.com/einaros/ws) then this would work.

One thing that is very disappointing in how .NET websockets are implemented is that HttpContext.AcceptWebSocketRequest() method is IIS7-specific and expects HttpWorkerRequest to be of IIS7WorkerRequest type, which makes it impossible for other HttpListener-based web server vendors to expose the same functionality without supplying proprietary APIs to access HttpListenerRequest which has all the websocket goodies in it. Microsoft should have added new members to HttpWorkerRequest to get access to websockets, and then in turn they should have implemented HttpContext.AcceptWebSocketRequest() so that it would rely on these new standard HttpWorkerRequest members instead of the non-public IIS7WorkerRequest.

I went through your samples first time around and they were very helpful.

The reason for that is we make http.sys-based web server for ASP.NET applications (http://ultidev.com/products/UWS/), and we simply need to expose WebSockets access to ASP.NET applications in the same way as IIS does.

However, ASP.NET team chose perplexing way of getting to WebSockets - instead of expanding the long-standing interface between ASP.NET and a web server, the HttpWorkerRequest class, ASP.NET team uses IIS7WorkerRequest.

It's been impossible to make Microsoft aware that there life on ASP.NET planet besides IIS, despite us having almost a million installations of our web server. We were unable to get onto WebPI despite being the only redistributable ASP.NET web server, got cold shoulder from WCF team when we found IIS dependencies there, and now WebSockets...

I have windows 8 & .net4.5 installed in the web server.im trying to achieve pushing system in the website.looked into html5 websocket, which is not compatibly with lower version of browsers, so from client side, need to use socket.io/nodejs or SignalR, those js lib to enable the client to use websocket. I get a bit confused, if i use Signal R or socket.io in the client side. what's the option for server side ? does the choice I made for client side effect what to use on server side ?

and I still not sure what exactly the code should look like in the server side.if from server side, it's a aspx page, then what is the link, called by client looks like ?

It sounds like SignalR or socket.io would be a good choice for your scenario. The important thing to note is that SignalR and socket.io are not just client side technologies - they both have client and server side components. SignalR has a .NET based server component while socket.io runs on node.js.

If you are comfortable developing for .NET, I suggest you look at SignalR. If you would prefer to work with JavaScript as your server side programming language then you should look at using socket.io. There are other options too, but I think these are worthwhile starting points.

Scott Hanselman has a good introductory post on SignalR here:http://www.hanselman.com/blog/AsynchronousScalableWebApplicationsWithRealtimePersistentLongrunningConnectionsWithSignalR.aspx

To answer your second post, yes I would start with SignalR (on both client and server). This page here has some information about selfhosting SignalR and this would be applicable to running in a Windows Service:https://github.com/SignalR/SignalR/wiki/Self-host

The SignalR room on Jabbr is a great way to connect with other SignalR users. You should try that here:http://jabbr.net/#/rooms/signalr

It is possible to create a websocket server without having to use some http listener (either IIS on asp.net or HttpListener outside iis)? So, simply connecting to the ws:// instead of upgrading an http connection.

The WebSocket protocol is designed around a HTTP upgrade mechanism, so it makes sense for it to be implemented on top of a webserver. If you take a look at a standalone WebSocket server (such as Fleck - https://github.com/statianzo/Fleck), it will still have some code to do the HTTP based handshake for establishing a WebSocket connection, but it won't serve normal HTTP requests. This is as close as you can get.

I have been trying for a while to get a C# websocket server running in Azure... as far as I understand this should now be possible (because Azure provides Windows Server 2012). However, I have a hard time getting it to work. Are there any samples for this scenario?

I am using a worker role that runs the server coder from your sample, and it seems to start o.k. in Azure. Unfortunately, when I connect from a client, it appears that the request is not recognized as a websocket request (the listenerContext.Request.IsWebSocketRequest returns false). Am I missing some configuration?

- using a web role instead of a worker role. I used a WCF web role template, ignored the service it specifies, and just start my own http listener, exactly as in your sample- adding "" to ServiceDefinition.csdef- not using port 80... for some reason, the problem described above (websocket requests are not recognized as such, but appear like normal http requests) still happens when I use port 80.

So it's not perfect yet since I would like to use port 80 but at least it runs.

I think the reason your above approach did not work on port 80 is that IIS has got control over port 80 (you picked web role). In this configuration, you could use the ASP.NET support for WebSockets instead of http listener (see my other sample) and that would work on port 80 (you will have to enable the WebSocket module in your IIS configuration).

Given that you want to use http listener, worker role would be best. Assuming you have the os family set correctly, you have an input endpoint setup in your role config, and you are using an up to date websocket client, I am struggling to think what else could be missing.

I agree it may work if I try a worker role one more time. However: it appears that websockets on port 80 get blocked quite often for a number of reasons beyond my control, like firewalls (https://github.com/LearnBoost/socket.io/wiki/Socket.IO-and-firewall-software) so I will stick with port 843 which seems to work just fine.

Yes, WebSocket connectivity on port 80 isn't particularly good. In practice I would recommend that you run the WebSocket traffic over SSL (and use default port of 443) because it makes a huge improvement to the connectivity success rate - the connection just looks like a standard SSL connection, and the intermediary can't tell that you're running WebSockets over it.

System.Net.Websockets provides a WebSocket Server funcctionality for a .NET application.

However, in a WINRT environment, I didn't see anything that will allow me to create a web sockcte server. In WINRT environment, we just have a Windows.Networking namespace which provides "WebSocket CLient" functionality.

DO u know if WINRT has any websocket server capability?

If not, how can we use System.Net.WebSockets namespace and implement a websocket server and bring that to a winrt environment (any hack?).

Unfortunately, I am not sure how you would bring websocket server capabilities to WinRT. You wouldn't be able to reuse the .NET 4.5 implementation because it requires either HttpListener or ASP.NET, neither of which are part of WinRT. If you were going to try to hack it together, I think the best way would be to take an open source .NET websocket implementation (there are a few out there), and modify it to use the WinRT socket API. I am not sure how feasible this is but that is what I would try.

Hi Paul,I have seen your video and downloaded the BasicAppNetChat application. I ran the code the way it is instructed in video. But in the chrome, I am getting an error as;error during WebSocket handshake: Unexpected response code: 200