Saturday 24 September 2011

Getting started with WebSockets in Windows 8

Update: Originally this post was written for the Windows 8 Developer Preview but most of the material is applicable for the Consumer Preview as well. My WebSocket samples project has been updated to be compatible with the Windows 8 Consumer Preview, so use this instead of the BUILD 2011 samples.

Last week I spoke at the BUILD conference about WebSockets. If you don’t have time to watch the talk, let me try to get you up to speed. The Windows 8 developer preview includes WebSockets support for:

  • IE 10
  • The new Windows Runtime
  • IIS 8.0
  • .NET 4.5
    • ASP.NET
    • WCF
    • HttpListener

During the talk Stefan and I did some demos with ASP.NET and WCF. The purpose of this post is to provide links to the source code for these demos and help you get them up and running in the Windows 8 developer preview.

The source code for these demos is now up on github:

https://github.com/paulbatum/BUILD-2011-WebSocket-Chat-Samples (note: this sample has not been updated for the Windows 8 Consumer Preview)
https://github.com/paulbatum/PushFrenzy

(If you’re not familiar with git and just want to download the source in a zip, just click the Downloads button on the github pages.)

Setting up the environment

Lets start from the beginning by grabbing a developer preview machine. For this tutorial I’ll be using the Windows Server developer preview which is available on MSDN for subscribers:

Operating Systems –> Windows Server Developer Preview –>

image

I’m using the server SKU because IIS is limited to 10 connections in the client SKU. However if you are not an MSDN subscriber you can still follow along by downloading the developer preview with developer tools at the Windows dev center. If you do this you can skip this next step where I install Visual Studio.

Update: The version of Visual Studio that comes pre-installed with the Windows developer preview is an express SKU and will not run these demos. Follow the instructions below to make sure you install the full version of the Visual Studio 11 developer preview.

Once the Windows 8 is up and running in Hyper-V I run the Visual Studio 11 developer preview installer. There are two ways to do this. Option one is to use the ISO that is available to MSDN subscribers:

Developer Tools –> Visual Studio 11 Developer Preview –>

image

Option two: Use the public installer available here:
http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=27543

After installing Visual Studio I enable IIS, the WebSocket module and HTTP activation for WCF to allow WCF to accept WebSockets connections. I add the Web Server role:

image

I enable ASP.NET 4.5 and HTTP Activation:

image

And I enable WebSockets for IIS:

image

The user interface will be different if you are doing this on the client SKU but the options you need to select are basically the same. Let me know in the comments if you are having difficulty.

If you are on the server SKU you’ll want to disable IE Enhanced Security Configuration (its on by default):

image

I’ll be using NuGet so I’ll install that too, using the Extension Manager in Visual Studio:

image

Opening and compiling the code

The good news is that after doing all that setup work, getting the sample apps up and running should be a piece of cake. One thing to be aware of is that WebSockets won’t run in IIS express at the moment. We’ll be using IIS 8.0, so you are going to be best off with running Visual Studio as an administrator.

The simplest sample would be the BasicAspNetChat sample. Open BasicAspNetChat.csproj in Visual Studio:

image

Update: IIS express might be on by default and if so this will cause problems. Right click on the project, select properties and go to the Web tab. You then need to untick “Use IIS Express” and save your changes:

image

If you’re running VS as an administrator your virtual directory should already be created and all you have to do is hit F5. IE 10 should load up and you’ll be prompted to enter a name:

image

Click the ‘Join chat’ button. This will establish the WebSocket connection. You can then chat with yourself by typing a message into the textbox and clicking ‘Broadcast Message’:

image

If you want to try out browser interoperability, download Google Chrome and give it a go. At time of writing, the stable build of Chrome is version 14, and this supports the same version of WebSockets as the Windows 8 developer preview. Just open up Chrome and browse to the same page and follow the same steps:

image

Curious about what is going on under the hood? Lets hit F12 in Chrome and then rejoin the chat:

image

Expand the headers on this and you can see the WebSocket handshake in action:

image

You should find the SignalRChat sample is easy to open and run. This sample is taking advantage of SignalR, which is an awesome open source project from my coworkers Damian Edwards and David Fowler. SignalR is basically Socket.IO for ASP.NET – it abstracts the underlying communication mechanism (long polling, websockets, etc) and it lets you do RPC style programming from JavaScript. The SignalR sample works the same as the basic chat sample described above, but the implementation makes use of SignalR rather than WebSockets directly.

The last sample I’ll mention today is my little game, Push Frenzy. When you open and run the project (make sure PushFrenzy.Web is the startup project), you should get this screen in IE 10:

image

To just test that it works, go ahead and enter your name, pick Solitaire mode and then click Play. You should see the game load up (it might take a few seconds on first run):

image

Just refresh the page to join a new game. Open two windows/tabs and have them both join a two player game. You should see that each player’s moves are instantly communicated to each other thanks to the power of WebSockets!

image

That’s it for today. Please let me know in the comments if you had any problems following these instructions. In future posts I’ll be diving into the APIs and looking at coding with WebSockets in more detail!

56 comments:

  1. I have try on Windows 8 and Windows Server 8, enabled IIS8, When I test on Visual Studio, context.IsWebSocketRequest is always false, how to fix that? Thanks

    ReplyDelete
  2. Sorry, I have fixed it by uncheck the Use IIS Express.

    ReplyDelete
  3. I forgot to point this out explicitly, I'll update my post. Thanks for mentioning it!

    ReplyDelete
  4. can i use WebSocket in IIS7.0?
    i want run my demo in some web servers instead of my console program.
    can i write a IIS extension module for websocket?
    Thanks

    ReplyDelete
  5. You can use WebSockets in IIS 8.0 as my samples demonstrate, but it won't work in earlier versions of IIS.

    ReplyDelete
  6. The samples work fine with IIS 8 on Windows Server 8, but I can't get socket connection from a Chrome 16+ browser running on a remote Windows 7 machine. What need to be changed to conduct a LAN test on the echo sample?

    ReplyDelete
  7. I believe Google just updated Chrome to use the very latest protocol version and you might be running into an incompatibility. You can double check this by using the f12 tools in chrome. Inspect the headers on the WebSocket handshake - if sec-websocket-version is 13 (rather than 8) then that would explain it.

    I suggest you try it from your remote Win7 machine with Firefox 7. Let me know if you're still having issues!

    ReplyDelete
  8. Hi,

    I am thinking of building a Silverlight websocket app against IIS 8. If I have IIS 8 exposes the websocket endpoint at TCP 4502. Would the Microsoft.ServiceModel.WebSockets.Silverlight.dll downloaded from HTML 5 lab work for the client side? Any document about this client component? Is there an update version of this dll?

    ReplyDelete
  9. You should find them to be compatible (but I haven't tried it myself) since they both use sec-websocket-version: 8 as part of the handshake. However I would caution you:

    - the HTML5 labs components are prototypes and have not been hardened for performance and security.

    - there is no guarantee that the prototypes will continue to be updated. You may find that the final version of IIS 8 implements a more recent version of the protocol than the HTML5 labs prototype.

    ReplyDelete
  10. Hi, I am having trouble getting .pdb files to generate. I can run the solution fine but want to be able to debug. I have it in debug mode, with no Optimize code options checked in Build tabs on Project Properties, as well as Debug Info set to full. Any ideas?

    ReplyDelete
  11. Have you looked for the pdb files and confirmed that they are not there? In the case of my game they should be in the pushfrenzy.web\bin folder.

    It sounds like you have all the right settings. What setup are you using? Are you using the Win8 client sku or server sku?

    ReplyDelete
  12. Thanks, I managed to get debugging to work after rebooting the VM

    ReplyDelete
  13. Thank you! This is the definitive overview for future WebSockets support in .NET. Extremely useful.

    ReplyDelete
  14. Thanks for the nice post, Paul - Windows 8 looks really good.

    It's always a challenge when a new technology is constrained by the latest and greatest O/S and browsers.
    Like many HTML5 capabilities, there are "polyfills" available for WebSockets as well. You, as a developer can code against the WebSocket APIs, but when the app is accessed from older browsers where native WebSocket support is not available, WebSocket emulation kicks in. WebSocket servers, like Kaazing, provide extremely efficient emulation techniques out there, working very well in IE8, IE7, even IE6.
    If interested in further details, you can read my post on the topic: http://blog.kaazing.com/?p=700

    ReplyDelete
  15. Thanks for a great guide, got it up and running in no time!

    ReplyDelete
  16. Is a way or reference for a web page written in HTML5 and use HTML5 WebSokcet (written in JAvaScript) to talk to WCF service (Console Application) using HTTP protocol?

    Thx

    ReplyDelete
  17. I don't have any sample code for this exact scenario, but the code for the Push Frenzy game I demoed in my build talk is pretty close to doing this. The project code is here:
    https://github.com/paulbatum/PushFrenzy

    Specifically, have a look at the code in the WebSocketServiceHostFactory:
    https://github.com/paulbatum/PushFrenzy/blob/master/PushFrenzy.Web/WebSocketServiceHostFactory.cs

    You can use the same code to create a WebSocketHost in your console app and then open it like you would with a normal WCF service.

    Hope this helps!

    ReplyDelete
  18. Hi Paul can you please tell me about the setting needs to be done for windows8 developer preview with vs2011

    I am using winows7 os with in that VM ware + Windows8 Developer preview + VS2011

    When I try to open the application I got the error "Failed to access IIS metabase"

    I solved this error by added new web project.

    But when ran the application it runs with out error, but it fails to connect the server and it is not hitting any break points.

    Can you please help me on this.

    ReplyDelete
  19. Rather than using the new web project you created, did you make sure you were running VS as an admin?

    ReplyDelete
  20. Thanks Paul I got the solution it worked fine for me,In windows8 developer preview administrative account was disabled, I enabled the account.

    ReplyDelete
  21. links in the article are no longer working.

    ReplyDelete
  22. Hi Paul,

    I'm getting a 403 forbidden when I launch the web application for PushFrenzy. Do you have any idea what's going wrong?

    Thanks,

    Wouter

    ReplyDelete
  23. Sorry about that, try navigating to the game.html page. I forgot that startup pages are a local setting and aren't persisted in the project file.

    ReplyDelete
  24. Hi Pavel,

    The WebSocket features in IIS and .NET require Windows 8. The behavior you are seeing is expected.

    ReplyDelete
  25. Hey Paul,

    Interesting question -- have you worked with ClientWebSocket? Assume, for a second, that I'd be building a platform that wants to receive/stream data from an HttpListener that upgrades itself to a WebSocketContext... I know your samples using the Metro libraries don't work anymore -- and I'm trying to find a way for my framework to be able to get data from WebSockets. The caveat, is that the framework is not an ASP.NET application, but think more of an aggregation-type server, which then might publish to other locations... So going through an HTML5 interface (as your samples do) or trying to create an AspNetWebSocket are completely out of the question.

    Any feedback you could give me? Or potential pitfalls/problems to look for on a client-side API, where we're not in a web-browser... at all?

    ReplyDelete
  26. I certainly have worked with ClientWebSocket and I've just updated the sample that was using the WinRT library to use ClientWebSocket instead. Have a look here: https://github.com/paulbatum/WebSocket-Samples/blob/master/HttpListenerWebSocketEcho/Client/Client.cs

    ReplyDelete
  27. Hi Paul,

    I've tried to run your PushFrenzy demo and am getting the following error when I try to create the Web Socket binding.

    Method not found: 'System.ServiceModel.Channels.WebSocketSettings System.ServiceModel.Channels.HttpTransportBindingElement.get_WebSocketSettings()'.

    It seems like I might be missing a part of the framework or perhaps it's changed recently? I'm using VS 2012 RC and Windows Server 2012 RC. I've followed all the steps, but no luck (both chat demos worked smoothly however).

    ReplyDelete
  28. Yeah I haven't updated the master branch for PushFrenzy in a while. Try the SignalR branch in the meantime. I will post when PushFrenzy is updated.

    ReplyDelete
  29. Method not found: 'System.ServiceModel.Channels.WebSocketSettings System.ServiceModel.Channels.HttpTransportBindingElement.get_WebSocketSettings()'.

    same problem for me Under Windows 8 Customer Preview. What a pity...

    ReplyDelete
  30. Paul, this may be a silly question from a newbe, but here it goes; I have a legacy application that e created on my server, is there anyway for SignalR/WIndows.websockets to allow me to run this app from an html5 compatible browser without installing anything on the client side. As well (websockets) part make me weary as I hate canvas because of its handling of video files and apps that require high refresh rates.

    ReplyDelete
  31. Hi flyon,

    You didn't describe what type of application your legacy app is, so I'm not sure what you're asking for exactly. But what I can tell you is that WebSockets (and SignalR) is just a communication technology. If you have an existing application that has a user interface built in something other than html (say Windows Forms), WebSockets is not going to solve your problem of how to get that user interface running in the browser.

    ReplyDelete
  32. Hi Paul,
    I was hoping perhaps that MS version of websockets would allow me to do the same thing that googles version does for numerous companies out there like Sparkview. Which they basically use it as middleware to talk to the TS server and thus create a client-less multi-browser solution to TS.

    ReplyDelete
  33. Microsoft's WebSockets implementation is standards compliant. If people have built TS style protocols to run over other WebSocket implementations then those same protocols should work on Microsoft's implementation.

    But I don't understand how this relates to your earlier comment about wanting to avoid canvas... You still need something in the browser that will render the UI.

    ReplyDelete
  34. That was why I said newbie, I was not sure if SignalR or MS websockets had their own alternative to canvas.

    ReplyDelete
  35. No problem, I just wanted to make sure I understood your question! The answer is no - they are simply communication technologies and you can use them with whatever UI you wish. You don't even have to use them with a browser (for example, the WinRT libraries for Metro style applications include APIs for WebSockets).

    ReplyDelete
  36. does anybody know how to fix the "Method not found: 'System.ServiceModel.Channels.WebSocketSettings System.ServiceModel.Channels.HttpTransportBindingElement.get_WebSocketSettings()'" error?

    ReplyDelete
  37. This is finally fixed. The master branch for PushFrenzy has been updated to be compatible with Windows 8 Release Preview.

    ReplyDelete
  38. Pulled the code of git at work to get a demo for our newly installed win2012 servers working and built a small chat app (might have been "similar" to yours...)

    Anyhow - I got the whole thing working without much effort thanks, but I am building principally apps for internal use on our domain - and some extensions to a legacy CRM4 thing... so windows authentication is the main ticket - I don't want to have to prompt the user for a domain password (again) and the browser already knows who they are - They come from a sharepoint web page.

    It may be all a bit too new - but I get the domain username passed via IIS Express in VS2012 - but when releasing to IIS8 and only having Windows Authentication - the ASPX page renders the name very nicely - but the socket never connects..

    From the client js/html side - I simply get the close event.

    Ive searched but so far no seems to have got to websockets and domain auth, is it even possible?...

    ReplyDelete
  39. Great question, but I haven't explored this before so this answer is going to be a guess. Maybe the way forward is to not require Windows Authentication on the WebSocket endpoint, but instead implement custom auth that requires a cookie that the browser received when it hit the aspx page with Windows Auth?

    Does that make any sense? :)

    ReplyDelete
  40. Yes ... I think the answer is there more or less

    I have another project that requires something similar with SSO/SSL etc... so the two may come to complement each other... We have AD so why put customers in a dodgy DB?...

    - our Infra chaps are still getting up to speed with Svr2012 so I think i'll find a good solution next week... sockets is the most exciting thing to happen for a long time and I've got everyone expecting a lot now... GULP

    My home lappy is still on win7 :-( Im waiting for win8 retail ... I was trying some things out earlier with express should have read:
    http://www.iis.net/learn/extensions/introduction-to-iis-express/iis-80-express-readme

    first..

    The socket didnt expose via standard error message the response - which is quite comprehensive as html page...

    Win7 + IIS8 Express does not support
    Server Name Indication (SNI)
    Central Certificate Store
    *** WebSocket Functionality ***

    So don't try!

    ReplyDelete
  41. Is there a way to use IIS to support CGI with websocket attachment to stdio, or pass raw socketid and allow application to pack/unpack websocket with stdio information?

    ReplyDelete
  42. I'm sorry but I don't understand the question, I have zero knowledge of CGI unfortunately.

    ReplyDelete
    Replies
    1. Paul, I just created a Server 2012 machine, installed IIS, then VS 2013, THEN added WebSockets to IIS. After some fiddling, your samples solution seems to load without incident, but when I run the AspNetChat sample, the websocket on the client throws an error, then a close. Any thoughts? Thanks! Curt (PA/USA)

      Delete
    2. I am not sure what the problem could be. I just pulled my samples and tried the AspNetChat out on a fresh Win 8.1 machine and didn't have any problems. My best guess is that it could be related to some browser issue? Are you using IE? Did you try from Chrome or Firefox?

      Delete
    3. Thanks, Paul. Yes, I am using IE, IE 11. I haven't tried the others. Which is the first c# file that's fired when IIS get a ws: request? And how does IIS know that connection? I looked in the web.config and whoa... There's not much there. I'm used to having a couple of custom http handlers, eh...

      Delete
    4. The AspNetChat example is using a NuGet package that we've stopped developing (in favor of SignalR) that hides most of the details. Take a look at my annotated echo example (in the same repository):
      http://paulbatum.github.io/WebSocket-Samples/AspNetWebSocketEcho/

      Delete
    5. Got it running - thanks, Paul. I do have one more question if you don't mind... Our application requires several thousand clients to all be "connected" at the same time. While we currently have a proprietary NT service supporting long polling on its own port, there's a strong desire to share the same port IIS is using - 80/443. Hence the interest in WebSockets... We do have another solution on the bench that uses asynchronous http handlers under asp.net / IIS 7. As long poll http requests come in, asp.net hands the request off to our code and we're able to delay it a minute before responding. Since we're using the asynch http handlers, we're able to relinquish precious threads back to asp.net while we delay the response. However, we quickly discovered that IIS/asp.net has a limit on the number of outstanding http requests - this number is on the order of a dozen or so, way less than the thousand or so we require. Additional requests simply get queued. We also discovered that asp,net apparently restarts itself every a day or two, causing any static state information to be lost. Similar to your example, we have a static collection to maintain state info for each client - that gets lost when asp.net restarts itself. How should we expect IIS 8 and WebSockets to perform? Will it be able to support thousands of simultaneous connections indefinitely out of the box? Thanks! -- Curt

      Delete
    6. Curt, I highly recommend you look at using SignalR. It wraps various different types of transports (websockets, long polling, etc) under one unified programming model and it supports scaling out to multiple nodes and persistent state using pluggable 'backplanes'. Start here: http://www.asp.net/signalr and be sure to check out the SignalR room on Jabbr (https://jabbr.net ) as there are always folks hanging out there happy to answer questions, etc. The SignalR community will definitely be able to help you with how to tweak ASP.NET for best throughput/scalability in realtime scenarios.

      Delete
  43. Hi Paul, I watched your aspnetChat video and it was excellent. I have compiled the code and modified it for our purposes and it all ran on IIS8.0 with Server 2012 and VStudio 2013 ok. When I ran it out of the VStudio environment it seems to run fine on the IIS8.0 when 'Add Application' is used and that points to the folder where the VStudio has created the output dll files, however I want to add as a handler and when I do that I add the dll's to the bin directory and it seems to add ok since the ChatHandler appears in the list, but the browser keep getting the 404 message not found. I use the following in the browser as a path //x.x.x.x/BasicAspNetChat/chat.ashx . As I say it works fine if added as an application.
    Also another query if we use the subprotocol property on the Javascript WebSocket() we have trouble connecting, if there a way of adding the subprotocol property to the IIS Server (it is our own defined protocol we are using). I notice your example did not use the subprotocol.
    going forward is it best to use the NuGet class library or the SignalR class, since the NuGet class is not still under development. we are planning to use WebSockets on the Client but a lot of customers seem to block it so we are testing for the https:// approach for better results. For SignalR does that require changes also on the Client Javascript side.
    Many thanks !

    ReplyDelete
  44. Hi Mark,

    I'm not sure whats going on with the 404's you are getting. For subprotocols, you can specify the subprotocol to accept when you call WebSocketContext.AcceptWebSocketRequest, by using the overload that takes an options object. See here:
    http://msdn.microsoft.com/en-us/library/hh195492(v=vs.110).aspx

    My strong recommendation is you switch to SignalR. Yes you'll need to make some changes on the client side, but its for the better. You'll get a much better connection success rate with SignalR since it can use multiple transport protocols. It also provides a much richer programming model and solves problems such as a scaling out to multiple instances.

    ReplyDelete
  45. Hi Paul

    how all this is related with GetExtensionVersion, HttpExtensionProc, TerminateExtension functions, which are exposed by IIS8 to build .dll modules? I mean: in HttpExtensionProc I can receive HTTP Upgrade request and reply with 101 response. What else can be done to continue from this point with Websockets over the same port 80? It must be some 'bridge' between technologies..

    Thanks
    Konstantin

    ReplyDelete
  46. Hi Konstantin,

    Unfortunately this is beyond my knowledge, I'm not familiar with the functions you are referring to.

    ReplyDelete
  47. Hi Paul,
    Sorry to bother you but I have a very quick question after watching your BUILD conference video. You said that you can directly call the IISWSOCK.DLL interface in IIS. Does this mean that it's a COM DLL so I could call it using old-fashioned Classic ASP? I'd appreciate a sample CreateObject if there is one!
    Many thanks.
    Regards,
    Gary

    ReplyDelete
  48. Hi Gary, unfortunately I have never tried this or anything similar. I know that a managed or native IIS module can leverage the built in WebSockets functionality in IIS, but I don't know whether this is possible from a classic ASP application.

    ReplyDelete
  49. Hi Gary, unfortunately I have never tried this or anything similar. I know that a managed or native IIS module can leverage the built in WebSockets functionality in IIS, but I don't know whether this is possible from a classic ASP application.

    ReplyDelete
  50. Hello Paul,

    I am hoping you are still taking questions or comments on this your post.

    Based on what I have read so far (your post and the ensuing comments/responses), the websockets approach may be the answer to what we are trying to do: We want to build a web application (ASP .NET) where each user (using IE,FF,Chrome,etc) will be able to use a locally- (client-) connected scanner to scan and submit ID cards to the web application server. That is, if the scanner is connected to the client machine as a USB device the browser will be able to communicate with and control it. I have searched far and wide but have come up empty because of the inherent sandbox/secure approach that current web application/browsers technologies are deployed. But I stumbled upon your post and I started thinking this may be the work-around. Please advise. Thanks in advance.

    Regards,

    Adesina

    ReplyDelete