SignalR: Awesome in Real-Time with ASP.NET
Edwards, Damian
Learn about the library that is making ASP.NET developers everywhere gasp in amazement. What is SignalR? It’s a persistent connection abstraction library for web development on .NET. Inspired by socket.io and now.js on Node, SignalR is allowing .NET developers to create experiences not previously possibly in a browser, with an easy to use high-level API that looks like magic.
 I am losing my voice, but I will do my best to get through this next hour for you. I'm a program manager on the ASP.net team at Microsoft, but today I'm going to be talking about a project that me and another guy on the ASP.net team, David Fowler, started in our own time last year called Signalar. Signalar is a persistent connection abstraction for.NET. So how many people have heard of Socket.io on Node? Okay, a few people, almost everybody, which is good. So Signalar is kind of like Socket.io for.NET, but we also have elements of Now.js, which is another library for Node that builds on top of Socket.io in Signalar as well. But again, it's all for.NET. And so if you're using Node already for real-time stuff, that's fantastic. Socket.io is a fantastic library. I'm not here to tell you that we're better than Node or anything. I'll leave that to tomorrow in the cage match with Rob Connery. But if you're a.NET developer and you want to do real-time development, then Signalar, I would hope, is something that you want to have a look at. So without further ado, I don't have any slides. I really don't like using slides these days because most of the talks I do are full of code. So let's just write some code and we'll learn how this thing works. So I'm going to start a new empty web application. And then I'm going to sort of new get in the world. So I'm going to say manage new get packages. And then from a local feed, I'm going to install Signalar.sample. So we have this working sample package for Signalar, if my machine is there. So here we go. That you can pull into your project. It pulls in all the required dependencies, obviously, that are needed to get Signalar itself working. And it pulls in some working code. So we can see here we have the beginnings of a stock ticker. Now, this is not a real stock ticker that connects to some service in the cloud. It's just some background thread that gets kicked off and fakes out of stock market. But it's a good indication. It's a good sort of learning tool to see how something might work. So let me go ahead and run that up. We can see that I've got that running over in one browser. I'm going to launch another instance and put that over here because real-time demos are always that much more impressive than we have two browsers. So hit me open market and you'll see that the changes are synchronized on both sides because we have two browsers connected to the same Signalar endpoint on the server and receiving information from the server and updating the UI as appropriate. So obviously in this case the client is JavaScript. We do support multiple clients and we'll talk about that later on. And the server, of course, is.NET. And I can go and hit close market here and you see it synchronizes on both sides. So while the majority of this is the server pushing to the client, when I click a button, obviously the client is pushing a message to the server and then that's resulting in the UI changing in both of the connected clients. So that's great, but let's go ahead and build something from scratch. That's perhaps a little bit simpler so that we can get an idea of what this looks like. So I'm going to add a new folder and we'll call it move shape. And inside this folder I'm going to add a class and I'm going to build my server-side logic for my move shape application. So I'm going to call this the move shape hub. So we have two levels of API server-side in Signalar. We have a low-level connection API, which is very similar to Socket.io. It is literally mimics a socket. So you open a connection, then you can send messages on it and you receive messages on it. You get an event when someone connects and you get an event when someone disconnects. And that's about it. So if all you care about is sort of the raw socket level stuff, you can program at that API and good luck to you. But most people like to use what we call hubs. We have this higher-level API called hubs, which lets me do reverse sort of procedure invocation from the server to the client. And vice versa, obviously the client can call the server. So I'm going to go ahead and create a hub. I'm going to derive from hub. I'm going to decorate this with an attribute that lets me change the hub name on the client. So I'm going to call it move shape on the client, because I like this word hub appearing there. I'm going to say public void, move shape. I'm going to take in an x and a y from my client. And whenever that happens, I'm going to go and tell the world that someone has moved a shape. And the way I do that is by accessing this client's member. And if I sort of zoom in here and have a look at clients, what you'll note is clients is dynamic. So clients has a property on hub, and clients represents all the people who are currently connected to this hub via signaler. And I can now go ahead and invoke a method in my client from my server-side code. Now that client might be JavaScript, it might be a.NET client, it might be iOS, it might be Monotouch. But in this case, it's going to be JavaScript. So this is dynamic, because obviously this isn't.NET code that's going to be running here. This is going to be something that's sent over the wire and invoked on the client. So I'm going to say shape moved, and I'm going to pass in the current connection ID. So that's going to be context.connectionID, so that they know who did it. And then the x and the y that was passed through. So that's my server code done. Let's add some client-side code. So I'm going to have JavaScript file, move shape. Now I need to pull in another library here, so I'm going to go back to newget, go to my Dropbox feed. I'm going to look for jQueryUI, install that. Wait a moment, pause for dramatic effect, there we go. I'm going to drag in jQuery, drag in jQueryUI, and I'm going to start writing some signaler client code. Actually I may as well drag in signaler in here as well. This is just for IntelliSense reasons. So I'm going to go ahead and get my hub. So that's dollar.connection.moveShape. We'll talk a little bit more about how that turned up in just a moment. And I'm going to have some type of UI on the screen that people can move around. So let's just say it's going to be an element called shape. So let's go ahead and find that. Okay, so now that I have my client-side hub, moveShape, I have to add that method that I want to be invoked. So if we go back here, we saw that I'm going to invoke a method called shapeMove. So let's add that method. I'm going to use jQuery's awesome extend method to do that. So for those of you who haven't used extend before, all it does is say take the object here and add anything that's on the second object to the first object. So I'm going to add a method called shapeMove. And that method has to take a number of parameters from the server. So connection ID, x and y. If we go back to here, you can see I'm passing connection ID, x and y. So I have a matching method signature on the client. And then I'm going to check to see that this wasn't invoked by myself. Because I'm going to be listening to all messages. And when I broadcast something to, when I send something to the server, I'm going to get that same message back again. So I'm just going to do a little check here to make sure that this isn't a message that originated from me. So I'm going to say if dollar.connection.hub.id is not equal to connection ID. So it's not from me that I want to go ahead and move the shape on the screen to this new position. So I'm going to say dollar.shapescss. Left is equal to x and y is equal to top. Oops, get my bracing right. Okay, so now that I have my client side method, I need to go ahead and wire up the client side logic and then call the server whenever I move this shape on the screen. It should be top equals y, I think, very much. And I've already got my first correction from the crowd. Fantastic, price for you, sir. Left, x. So now I have to go ahead and wire up the client. So first I need to go ahead and start the connection. So I'm going to say dollar.connection.hub.start. And then when that's done, I'm going to pass in a callback here that will get invoked once my connection has actually started. I want to go ahead and enable the sort of dragging behavior so this can get moved around. So I'm going to say shape.dragable, which is that jQuery UI function that I brought in. And I say when that gets dragged, go ahead and invoke this function. And when that's dragged, I want to call the server and tell the server, hey, what's the position of the shape? So I'm going to say hub.moveShape. So again, moveShape is this method here on the server. So this is my hub. I'm going to call hub.moveShape. And I have to pass in x and y. So that's just this.offsetLeft, this.offsetTop. Like so. Okay, so that's my client-side code done. Let's add a page to actually show it on. Let's add all these JavaScript packages that I need. So I need that one, I need that one, I need that one. Let's drag those into here. And I need to add an extra magic script reference that we'll look at in just a moment. That's going to pull down some dynamically generated JavaScript to make this sort of signal magic happen. So signalr slash hobs. I'm going to add my div with an ID of shape. And so that you can actually see my shape, let's add a style block. And we'll say shape. Width is 100 pixels. Height is 100 pixels. And background color is some new... Let's have a look. This time blue over here looks pretty good. Okay, so that's my app. Let's run that up, see if I made any mistakes. Okay, so it's showing there, that's a good start. Let's open another browser instance, put that over here. Paste that in there. And if I pick this up and move it, you can see that it moves in both sides. So really, really easy to get going with signalr doing these type of broadcast scenarios. So let's tease apart this demo a little bit now and try and get an understanding of why this even works and what's going on under the covers. Okay, so let's have a look. Let's bring up the network tab here and we'll hit F5. We'll see a few things that happen when zooming down here. So as Remember I said, signalr is an abstraction. It's an abstraction over various ways that we can in HTTP mimic or actually achieve a full persistent connection between the client and the server. So how many people have heard of WebSockets? Everybody. Okay, good. WebSockets is kind of synonymous with this new move to the real-time web. The problem with WebSockets is they don't work. They might work if you have a browser that supports them. If you're a.NET developer, they'll work in ASP.NET if you have Windows 8 on your server and using.NET 4.5. They'll work if your hosting provider supports WebSockets through their reverse proxy and load balancing infrastructure. And if your client is behind a firewall or a proxy that also won't trample on WebSockets. If all of those things are true, then yes, you'll get a WebSocket connection from your client to your server. Now, we know all those things aren't going to be true for quite some time yet for the vast majority of people. And so libraries like SignalR and Socket.io exist to help us bridge that gap. What do we use when WebSockets isn't available? They also give us a much nicer, higher-level API. Who's actually programmed with WebSockets? Okay, only a couple of people. It's hard. WebSockets is sockets. So you don't get any of the niceties I just showed you. It's open a socket, send a message. So you have to do all your own dispatching. You have to do your own invocation logic. It's basically just sending strings or binary data back and forth. If you've ever done socket programming before with raw sockets, it's basically similar. And the server-side programming, and that's just the client side, the server-side programming is even harder. There's a specific way you have to do WebSocket framing. You have to ensure that messages are sent in order. You have to ensure that you're only ever sending one message at a time on a connection. So there's all these types of buffering and synchronization code that you have to write if you're not using a framework that does that for you. So it's nice to have a high-level framework so that I don't have to worry about that type of stuff. So if I don't have WebSockets, what can I use? So we fall back to a number of different things. So if we come down to this request down here, you can see that there's a request to an endpoint called Negotiate. So the first thing that SignalR will do is make a standard Ajax call to the server saying, hey, I need to negotiate a transport. I need to figure out what can I use for me, client, to talk to you, server, in somewhat of a real-time fashion. Now, we'll start out with WebSockets, and then we fall back from there. Now, we'll only attempt to use WebSockets if the server says it can support WebSockets. If you're running on top of ASP.NET, that means you're on ASP.NET 4.5 on Windows 8 with IIS Express 8 or IIS Express 8. Now, most people aren't there yet, so most of the time you're not going to be using WebSockets just yet. You'll then fall down to something called Server-Send Events or Event Source. Server-Send Events is a technique or actually an API that you can use in the browser in all browsers except IE. That lets you have a persistent connection from the server to the client such that the server can push information down to the client. So if WebSockets isn't available, we'll try and use Event Source. That will generally work in all browsers except for IE. So we skipped Event Source for IE, and then we go down to the next level, which is Forever Frame. Anyone ever tried using Forever Frame? Ever heard of that technique? A couple of hands go up. So Forever Frame is the idea of having an iframe embedded in your document that makes a request, loads of document from the server, and all that document in the iframe does is spit out script tags, and it never finishes. So it's just an ever-growing document full of script tags, and the great thing about browsers is that they'll execute script tags as they get them, even before the page is finished loading. So you can have a hidden iframe with a document in it that gets script tags that contain the messages that you want to be sent to the client, and it'll happily keep invoking them for you. So Forever Frame will be used generally in IE because it supports Forever Frame quite well. And then if none of those things are supported, which is unusual, but it can happen depending on the infrastructure between the client and the server, perhaps the router or something doesn't like a persistent HTTP connection, then we fall back to the lowest level, which is long polling. So the idea of long polling, when we all know what polling is, right, polling is, I call the server, have you got data? It replies no. So I say, okay, after some period of time, I call the server again. Do you have data now? No. So I wait a little bit longer, and they say, hey, have you got data now? Yes. Okay, so now I have data, and then I wait a little bit more, and then I poll. Long polling is the idea of saying, let me call the server and say, have you got data? And the server doesn't return until it does. And so that connection stays open until there is data available to sort of fill that request. And then once that request comes back, I process it on the client, and then I send immediately another request saying, hey, have you got any more data? And then that stays open until there is more data. So long polling is advantage over polling in that while there is no data flowing, you have an open connection, but you're not really using any resources other than those taken up by an open connection. You're not constantly hitting the server with a request that doesn't result in any data, which is kind of nice. It also has very low latency compared to polling because you're going to get the data as soon as the data is available, assuming you have a connection open. So we had a negotiate request, and after that we had a connect request. And if we look at the URL for this, zoom out a little bit, we can see that over here, we have signalize slash connect. So now that I've done my negotiation, I'm going to connect to the server with the connect verb. I'm going to say transport equals server-cent events. So the client and the server negotiated server-cent events because WebSockets wasn't available. And then server-cent events, as I said, is this one that Chrome, Firefox, Opera, Safari support. And then once that's open, what we'll see is that thing stays open. So we should see over here, here's that server-cent events message over there. You can see it's been over open for two minutes, been receiving for two minutes. And if I come over and open another browser now, let's do this one over here, so let's push this one back. And if I move this around, we'll see that that bar changes if it doesn't make a lot of me. Let's see if I can make this a little bit easier to see. It might be easier if I just refresh. There we go. So here's my connect down here. As I move this around, see how that gets longer because it's currently receiving information from the server so that load time for that request just keeps getting longer and longer and longer. And that request will just stay open while it's receiving data until either the timeout kicks in. So there's a default timeout of two minutes at which point it'll reconnect or something goes wrong, obviously. Okay, so that's sort of the intrinsics of negotiation, negotiated transport, and then get a connection as a result of that. So what else happened in that negotiate request? Because there's other interesting things that happen in here. We zoom into here and have a look at what was returned. So we get a JSON payload back from the server when we negotiate, which gives us a URL, and we get a connection ID. So that's interesting. We know that every connection that connects to Signaler gets a unique connection ID. Now, in this case, it's a GUID. You don't really have to worry about it. We'll have a look a little bit later on when you'd need to worry about mapping this connection to something useful. But this means that you can address people individually using Signaler because you have a connection ID through which you can identify them, which is kind of cool. You can also see that we sent back a flag saying whether we should try WebSockets. So on the server, we determined whether WebSockets was even going to be supported. And if it wasn't, we tell the client, don't even bother trying because it's not going to work. Okay. So that was a very, very simple demo. Let's move on to something a little bit more convoluted. We do support something, we do support more clients than just JavaScript. So let's open up a slightly more complete version of this application. Let me go ahead and find it. And let's open this one here. So this is the same demo that we just saw. It's move shape. It has move shape. It's basically the same thing that I just showed you. It's just a little bit more UI and a little bit more logic in the client. But other than that, it's the same. So if I run it up, you can see here it's pretty much the same as we had before. And now I'm telling you how many clients are currently connected as well. So I've got this number in the top right-hand corner. So how many people are currently connected? So what we also have here, though, is a different sort of client. I have a WPF client. So I'm going to come in here. I'm going to show up this move shape desktop. Come back and open this one. Let me pin this to the right. And now when I move this around, you'll see that I've got my WPF client also receiving this information from the right-hand side. And similarly, I can move from the left to the right. So the code for this looks pretty similar. Let's go back and have a look. So let's have a look at my... I'm not the greatest WPF programmer in the world, but I can sort of model my way through it. So it's just a canvas with a shape inside of it and a text block for the number of clients. And then the code behind for this canvas is... I have an async void method go because SignalR is async from top to bottom. In order to scale in ASP.NET, it needs to be asynchronous. If you're going to keep connections open for a long period of time, they have to be asynchronous because you don't want to be using a thread when that connection is doing nothing because you're just going to run out of threads and then your server won't be able to serve any more connections. And so SignalR is async top to bottom, both on the client and the server. And so you can see I go ahead and it looks kind of similar to the JavaScript code. I knew up a hub connection. I go ahead and create a proxy for that hub connection. Now in JavaScript, that was done for me automatically. I'll go back in a minute and show you how that happened. But when I imported that JavaScript slash SignalR slash hubs, that was a hub proxy being created for me. So I have to create it manually over here in.NET world. And then rather than doing method invocation, I'm handling method events. So I'm saying when the hub raises an event called shape moved, go ahead and invoke this delegate using these strongly typed parameters. So connection ID XY. And look very, very, again, very similar to what we had in JavaScript. Although now it looks like WPF. I check if it wasn't myself and then if it wasn't, I go ahead and invoke this delegate back on the UI thread to go ahead and move the shape on the canvas. And now that I'm also tracking connected clients, I get a message whenever that client count changes. So when I connected and I got two clients, I got a message and I go and invoke that as well. Then I go ahead and start the connection. And I await that because it's asynchronous. And then once that's finished, I go ahead and enable the draggable UI. Now this draggable is just my own sort of ghetto extension for WPF that makes something draggable on a canvas. So don't worry too much about that. I've just sort of emulated what jQuery UI does. So I've said it's draggable and then when anyone drags it, go ahead and invoke this lambda and tell the hub to invoke the move shape method and set the left and top based to what this is here. So kind of the same stuff. So there is an interesting thing that was different on the server though. Let's have a look at that. So move shape. So here's my hub, very similar to the one we had before. But I've got two interfaces that I'm implementing this time that I wasn't before. I connected and I disconnect. So signal as a connection abstraction gives you connect and disconnect semantics. And so you can get alerted whenever someone connects to your hub or your connection and alerted when they disconnect as well. And so for a hub, the way to do that is to implement these two interfaces. I connected and I disconnect. And then we will invoke your connect method whenever someone connects to the hub and we'll invoke your disconnect method whenever someone disconnects from the hub. Now we also have a reconnect intrinsic, which you can handle as well if you want to. And that can be useful to ensure that when clients reconnect, they are going to say that they're a member of a period of groups and you can check whether that's actually true. So I'll talk about that a little bit more in a minute. So the interesting thing here is that I'm showing how you can go ahead and track connections. So one of the questions we very often get when talking about SignalR is, how do I get a list of clients? And the answer is you don't, because there is no list of clients. SignalR at its core is built on a PubSub mechanism. In order to enable scale out, which we're going to look at a little bit later, we don't store state. So if we were able to give you a list of clients, it would be very difficult for us to scale that out in a web farm because obviously you can have a thousand clients connected to one server and a thousand clients connected to another. And if your code is running on the second server and says, give me a list of clients, how does it know what clients are connected to the first server? Unless you're sharing some sort of back end state. And so there is no list of clients. What you have is a list of signals, not even a list, just arbitrary keys, arbitrary signals that you can broadcast to at its very, very core. Every client gets its own signal, that's what that connection ID is. Every endpoint gets its own signal. So this move shape hub will have a signal called move shape hub. And whenever you send a message to move shape hub, we literally send a message through the message bar that says, broadcast to move shape hub this payload. And the payload for hubs will include what method it is that you want to invoke and the arguments that you want to pass to that method. And so it's up to you to track connections and who exists on what connection. So in this case, I just have a static concurrent dictionary, because this is asynchronous. I could have multiple threads operating on this hub at one time, so I have to have a concurrent dictionary of connections because it's static. And then whenever connect is called, I go ahead and just add a record to that concurrent dictionary keyed by the connection ID. And then I go ahead and broadcast out to all clients the current counter to that dictionary. So I'm just using this dictionary as a way to track how many people there currently are in my app. Now, obviously, this wouldn't scale out because it's a static in-memory dictionary on this class. But you can imagine in a proper application, this would be stored in a database or in some type of distributed cache so that you could actually do proper how many people are currently connected sort of intrinsics. So similarly on disconnect, I go ahead and try to remove that and I now update the counter appropriately. Now, what isn't shown here, which is interesting to note, is that the relationship from users to connections is one to many. So if you have the concept of authentication in your application, then obviously people will log in using some type of credential and then they have some type of username, so it might be Damian in my case. And then when I use SignalR, I'm logged into your app as Damian, and then I'm going to connect to your app with a connection and that connection has a connection ID. So I need to store somewhere the fact that Damian is currently on connection 1, 2, 3, 4. And so that should be persisted away in your database or persistent mechanism so that when someone says, hey, I want to broadcast a message to Damian, you can look up the connection ID that Damian is currently on and then send a message to that connection ID. Now, I did say it was one to many though. I mean, I can obviously open more than one browser, or I can open a browser and iOS app or a Windows phone app and connect to the same thing with the same user, but I'll have different SignalR connections. So the recommended practice is to ensure that you're storing one user to multiple connections. Now, for a good example of how this works, we have sort of our smoke test app up in the cloud, this chat app called Jabba. So Jabba is sort of an IRC clone written on top of SignalR. It's hosted up on Windows Azure, but that's kind of incidental. And it's the sources available in GitHub, so you can go and see what it's like to build an ASP.NET application of this nature that's real-time using SignalR. And this uses SQL Server, it's underlying persistence mechanism, so you can see how all the user names are persisted, how the user names are mapped to individual connections, how we handle connect and disconnect. You can see as I'm talking here, people are typing and we're getting little speech bubbles that come up when they're typing, so it's more than just messages flowing back and forth. We actually have things like status indications as well. Jabba has some really interesting stuff as well. It has content providers, so if I keep scrolling up here, I should be able to find an example where someone has posted a JPEG, like so, and then we have sort of built-in content providers that will then go down and pull down that JPEG and throw it in the room for you, which is kind of cool. So it's a really nice application for learning the type of things you can do with SignalR and what you can do with real-time. So, well worth pointing out. It does get a little bit wacky in general chat sometimes, so I tend to stick into the more focused rooms, so to say. Okay, so let's go back to the JavaScript client for a moment because I talked about this creation of the proxy that I didn't really elaborate on. So if we go back to my index, we can see this SignalR slash hubs request that I put in here as a JavaScript file. Let's have a look at what that actually is. So let's bring up my network stack again. It's at F5. Let's find that one in here. So here it is, SignalR slash hubs. So we can see what we pulled down was a JavaScript file, but this JavaScript file was dynamically generated on the server. And if we scroll down, there's a whole bunch of wire-up stuff which is interesting, but not what I really care about. What we'll see down here is this part. This call to $.extendSignalR with myHubs. And so you can see MoveShape was my class, my C-sharp class on the server got turned into this JavaScript object that has a method that I can invoke that goes ahead and calls this server call function to actually make the call on the server. So it kind of appears like magic, but really all that we're doing is generating some JavaScript. It's really generating a proxy, just like you would have done back in the old days when you added an Asmx reference or WCF reference using Add Service Reference in Visual Studio. And then it would generate you a JavaScript proxy if you added it to the script manager in webforms. It's kind of similar except we do it at runtime. And we also allow the server to call back into the client. And so we get this really, really nice sort of back-and-forward remote procedure call paradigm that we can do between the client and the server, which is kind of cool. Okay, so that's how that works. Let's have a look at some other interesting things. So WebSockets. So I said that WebSockets wasn't running in this demo and it isn't. So the version of SignalR that's available up in Nuget right now is 0.5.0. The next version, 0.5.1, will come with WebSockets support in the box. So I actually have the source application open right here so we can have a look at what WebSockets support looks like just to prove to you that it does work. So it does require Windows 8 on the server, so I'm running Windows 8 Release Preview here. I'm running Visual Studio 2012. Oops, that's a known problem. Let's go back and close that and try that again. Rebuild. I'm running Visual Studio 2012 RC, which comes with IS Express 8. And so because I'm running IS Express 8 on top of Windows 8, I get WebSockets. So if I F12 in here and I hit F5, what we'll see down here is a different sort of request. So I'm in a browser that supports WebSockets. I'm in Chrome. And we can see the negotiate happened. If we look at the negotiate this time, we can see that Try WebSockets is true. So we're going to get an attempt for WebSockets, which is good. And I get this, Connect Raw. We can see that the URL there says transport equals WebSockets. And then you can see the status from the server was 101 switching protocols. So this is how WebSockets works. WebSockets is an upgrade request. A standard request is made to the server. It's a get request. You can see that here, get. And then it says in there, there is a header that says, hey, I want to upgrade this request to a WebSocket request. And then if the server replies with the 101, that means, yes, party on, we now have a WebSocket. We can now do persistent connection. And so we won't see any other, if I go ahead and start broadcasting stuff now, there are no other requests happening because I have a WebSocket. This thing is just there happening underneath the covers now. Now, I do have Chrome Canary installed here. And in theory, ooh, okay, see what that does. Chrome Canary is supposed to give me WebSocket inspection capabilities. Let's have a look at this works. I've actually tried this. I'm going off script here. So let's go network. Let's F5. Here it is. There's my WebSocket. And if I go to here and I go to WebSocket, look at that. There's my WebSocket frame. Sweet. So if I broadcast stuff and I come back to here, there's the WebSocket frame. So you can actually see the messages flowing over the WebSocket. And it even shows you the direction. So this is saying coming from the server, that right to left. And this is the JSON payload that Signaler was sending back from the server to the client. So you may have noticed that Signaler has its own protocol. You connect to a Signaler server with a Signaler client. It's much like Socket.io. This is our JSON protocol. So we wrap whatever message that you send, which is we serialize whatever you send as JSON, you can just send random.net objects. We'll serialize them with JSON. And then we wrap that with sort of a message framing protocol, which itself is JSON as well. And so that's what you'll see flowing over the wire. So that's kind of cool. We've got WebSockets running there, which is nice. So we have some other samples in our sort of sample project that's up in source. That's my daughter, Elizabeth. That was raw connection that I just showed you there. We have an example of just streaming. So in this case, all we have is there's a background thread on the server that is just pumping messages to the client. So rather than any type of interactivity, I just have a dumb client that's just listening passively to messages. A bit similar to the stock ticker sample I showed you originally. We have this mouse tracking one, which is kind of cool. So every person who connects gets a cursor and with a little number on it. And you can see that update in real time, which is kind of nice. We had that up to some ridiculous number and it does get a little bit strange after you've got dozens and dozens or even hundreds of people in there. We have this one called ShapeShare, which is sort of a more advanced version of the MoveShape demo I showed you. So I can put this one, I can actually add a username in here. So I have left, right, and then I can add a rectangle and I can move that round and I can add a picture. And I can move that round and I can sort of resize that. And you can see that it says change by right. And if I move it, it says change by right over here. It says change by left. So the source for that one is quite interesting because it shows mapping usernames to connection IDs. So that one is worth checking out when you go and get latest from GitHub. And then we have a drawing pad. Someone contributed this one. So this is using Canvas to go ahead and do sort of multiple people drawing in the same pad at the same time, which is kind of nice. And we have chat, but chat is basically what turned into Java. So I'm not going to bother showing that. So connection status is interesting. So I talked about the fact that we do connection intrinsics for you. We manage connect and disconnect. We also have the concept of reconnect. So some of these transports aren't truly persistent. So WebSockets is a persistent connection. It's bidirectional, it's open. You can send stuff both ways and it stays open. But all of the other transports aren't actually full duplex. Service and events in Forever Frame will keep a connection open over which the server can send stuff to the client. But the client, when it sends to the server, it just makes an Ajax post. And we sort of hide all that under the layers for you. So what happens when the underlying receive channel goes away? I mean, it's the internet. Sometimes things go bad. So we have built-in retry logic. So if the connection goes down for whatever reason, we'll reconnect and we'll continue trying to reconnect until the server comes back up again. Now, by default, well, until last night, I was just looking at the check-ins and we've actually changed this behavior, we used to have, we do have the concept of a time-out, so you can actually set a value that says, keep the receive channel open for this amount of time and then forcibly close it, forcing the client to reconnect. That can be useful in certain situations, depending on what your load balancing infrastructure is like. But now we actually have the idea of Keep Alive. So by default now, from source anyway, not in 0.50, but in 5.1, we have a Keep Alive packet that will be sent. So while that connection is open, we will ping from server to client an empty payload just to keep the connection open. And that will trick load balances like those used in Azure and App Harbour and those type of things to not terminate the TCP connection. Because what we find is that a lot of hosting companies, their infrastructure for sort of handling connections, if they see a connection that isn't doing anything for a period of time, they'll just abort it. And so you have to be able to keep sending information over that, like a heartbeat ping, to keep that connection open. So we do that for you by default now in 0.5.1, which will be out very shortly. So because we have Keep Alive now, this actually won't drop. This will actually stay open. What you would see is if it reconnected, if it did drop, we'll go ahead and reconnect for you. And we will raise that event to your code so you can handle reconnect if you want to, but most of the time you don't have to worry about it. The thing will just reconnect. And you can see here that as soon as I disconnected on this side, I got the red saying that I left. So we handled that disconnect for you as well. Disconnect is a really, really interesting issue. Detecting when someone disconnects from your web server is actually really, really difficult, because there is a lot of different ways people can disconnect. So the reason that worked so well this time is we recently added support for graceful disconnect. So when we actually listen to the events in the browsers that support them that say the person is navigating away from this page, like the window on Unload, and if it does, we will try and send a packet to the server saying this connection is about to be closed. Because if you hit F5, what you're basically doing is killing one connection and then reopening another one. Connections don't last beyond pages, of course, because they only open as long as that JavaScript is running. And so when I navigated away from that page, you can see that I got disconnected on the left-hand side because we sent a packet to the server saying I disconnected. If for some reason that packet wasn't able to reach the server, then we have a background thread that runs on your application on the server that does know about all the connections for that server, because you might be running in a web farm, and will every 20 seconds or so check every single one of those connections and see whether the client is still connected. So IIS does have the concept of is client connected? There's a property on the response object. You can check if the client is still connected. And if that's false, then we look at some threshold, and if you're over the sort of the disconnect threshold, then we'll go ahead and fire the disconnect event, raise that up to your code, and you'll be able to do whatever it is that makes sense in your application for when you use the disconnects. Now, when talking about reconnect, that kind of suggests that there's a period where connections aren't open. And so what happens if messages are sent to the user while your underlying connection isn't actually open? It's a little bit hard to demonstrate, but you can imagine here that, let's see if I can actually demonstrate this. Let's see if I can put a break point. So the server is sending messages, and we can see on the left-hand side the one that isn't going to get broken here. So I'm going to come over to my...where is it? I'm going to come over to...resources, thank you. No, that's not what I wanted to... I'm in Canary, which is what's making this difficult. It looks like it's different. Let's come over to here. Okay, scripts is what I wanted. Let's come over to SignalR. So we can see this one. Let me just shift these around so I can see them a bit better. So the one over the left is going to keep running. Drag...no...oh, this is not looking good. Let's try that again. Where is that? Ah, now I've lost it completely. That one is that one. Let's put that one there. That one is that one. Okay, let's pull that one off. There we go. Put that one over there. Okay, so what we want to do is find the transport logic that's going to handle events. So here's service and events. I know that's what I'm using. I'm actually using WebSockets to process messages. Transport...da, da, da, da, da. Here we go. So I'm going to put a break point here. Okay, so I'm broken. And so over here, you can see the left-hand side is still getting messages. And the right-hand side isn't. Well, you can't scroll, but you can assume that it's not. And now if I hit play and I get rid of that break point, we'll see that I didn't miss any messages. I got all the same number of messages. So you can see 21, 23, 25, 27, 29, 31, 33, 35. It goes up by two every single time. I didn't miss any messages, even though that connection wasn't open at the point that those messages were coming through from the server. And that's because on the server, we buffer messages. So we have an in-memory buffer so that while connections are in their sort of their reconnect phase, where they're trying to reconnect again, we'll store those messages in memory. And then when the connection reconnects, it always says, hey, give me every message since message 47. Because that's the last one I got. And then if the message is since then, we'll send those messages down and the connection will go in its merry way. So that's how we handle reconnect, which is kind of nice. Okay. Scale out. So one of the questions that most people ask, first questions that most people ask, is usually two. How does it scale? Like, how many connections can you support? And how do you do scale out? Well, I'm glad you asked. Let's have a look at that. So we built SignalR with the ability to scale out in mind from the very, very beginning. So that's why we don't store state, like a list of connections which we enumerate over to do stuff. What we do do is base things on a PubSub mechanism. And so all you need to do is have some type of message backplane across your web farm that you can use so that if you've got one server here, another server here, you've got 100 people connected to this server and 100 people connected to that server, if I broadcast from server one, I want to make sure that all the people on server two get that message as well. You need to have some type of common backplane for that to work. And we currently ship two backplanes that we support. One is Redis. So who's used Redis at all, anyone? Oh, no one has used Redis. Wow. Is everyone here a.NET programmer, I'm guessing? Yes, that's why you've not used Redis. So Redis is an in-memory database that's very popular in sort of the Linux world. But MS Open Tech, the new open source subsidiary of Microsoft, has released as its first open source project a port of Redis for Windows. So we have a Redis provider for SignalR to do scale out and we have an Azure service bus provider. So if you're deploying SignalR in Azure with multiple nodes, you can plug it into Azure service bus as the backplane for the messages between your nodes. So let's use Redis because I'm just running on my local bus, my local machine here. So I'm going to come up to my app start. And you'll note that I already have an app start method set up here ready to go. I just got this commented out. So I've already installed a package called SignalR.Redis. So I just go to newget, install SignalR.Redis, which is going to pull in the bits that I need to use Redis and SignalR into my project. And then it's going to add an extension method hanging off our I dependency resolver type that says useRedis. And so all I have to do is pass in the address to the Redis server, the port, the password if there is one, and the event key I want to use to sort of segregate my messages for this app. And that's it. And so if I build that, I now have to go off and obviously start Redis because my Redis server isn't running. So let's do that. So this is PowerShell. I've literally gone to GitHub. I've cloned the Redis for Windows repository from GitHub and I built it using Visual Studio. OK, it's C++. I just upgraded it from 2010 to 2012. And then I built it. And then I went to the debug folder and I'm running start process Redis.server. So now Redis is running on my box. It's running on port 6379, which is good because that's what I configured it for, 6379. So that's good. And then what I'm going to do is I have another command over here, which is going to kick off, where is it? This one. I'm going to start my web farm. So it's not good doing scale out unless I have more than one web server. So here I have two web servers. I've got IS Express on one side listening on port 8090 and then IS Express on another side listening on port 8091. So let's kind of reorganize all these windows so this makes sense. So here we go. This is sort of a visual idea here. We have one server on the left, one server on the right. Redis in the middle. OK, that's kind of cool. So let's go ahead and connect some clients to this. So let's get my browser running. Let's get one browser connected to... Let's see if I can do the resize shuffle here. Get one browser connected to a local host. I want this to go to 8090 slash move shape. So that you can see over here that IS spat out some stuff saying that things are happening. So let's open another browser and move that one over here. And we'll connect that one to the other web server. So you can imagine that I was in front of... I have a load balancer, right? And I'm actually just going to the same address. And now when I drag, you can see that it's working. So a little bit lagged this time. And it looks like I killed something. Demo fail. Oh, there we go. It's just lagging. My machine is getting a little bit wacky. You can see it did catch up. So even though it lagged, it did actually eventually catch up. All the messages got through. So now that it's warmed up, it's actually working quite well. So I now have two completely different web servers. So my application is running twice in two separate processes. So there's nothing shared between these processes. And all the cross-process communication is happening through Redis, which is kind of cool. Now, the one thing that isn't working, as you can see, is my connection count is wrong. So can anyone tell me why my connection count is wrong? I didn't saw that in Redis. Remember, it was just in a static dictionary. So I've got a connection count of one in each server, which is correct for each server. But obviously, if I was writing this app to be scale-out-friendly, I'd have to put that sort of information in some type of back-end, either in a Redis store or a C-consever or something like that. But that shows you just how easy it is to get scale-out working with SignalR using something like Redis. Okay, so that's kind of cool. So that's one of the questions answered that people always ask, which is, how do I do scale-out with SignalR? Well, you can. The other question is usually around load and scale. How many connections can you support? Well, I can tell you that, well, and we take this very, very seriously, where we obviously want SignalR to be as performant as it possibly can be and support as many connections as it can. With the current build on my machine at home, which is a Core i7-920, which is like a first-generation Core i7, it's about three years old, so it's not a new machine by any stretch, but it's quad-core, hyper-threaded, so it's a decent machine, but you could build one today for four or 500 bucks. I can, with 5,000 clients broadcasting at 10 or 20 messages a second, get about 30,000 cents per second in that infrastructure. So that's pretty good. And a three-year-old machine getting about 30,000 cents per second for 5,000 clients. Our bottleneck at the moment isn't CPU. In fact, the CPU doesn't max out during that test. Our bottleneck is contention. We have a fundamental flaw in our Core architecture. In 0.6, we're going to be re-implementing the Core of SignalR, excuse me, to change how we sort of do our Core level PubSub infrastructure, and we expect that number to drastically improve. So we've got some very smart people on the ASP.net team, much smarter than me, building custom data structures for doing message management at the moment. So as I said, we have an in-memory message store, and at the moment we have some issues with garbage collection because messages live for a while before they go away. So while it works very, very well, and when you get under really, really heavy load, like crazy heavy load with thousands of messages a second, you can certainly run into issues. We have new message stores, infrastructures, which can do millions and millions and millions of messages a second without breaking a sweat. So over the next four to eight weeks, we're going to integrate that into the Core of SignalR, and in 0.6, you should see the benefits of that. And as I said, we'd certainly expect the throughput numbers to at least double, and if not triple. So I'm certainly shooting for hopefully six-digit sort of messages per second throughput on my setup at home. But that's all good. That's just talk. Let's get a low test up and running here right now so you can sort of see how this works and what tools we use to do our low testing. So we have a performance harness for SignalR that we wrote called Flywheel. We have these crazy names. I don't know how it started. I think it started when David wrote a load generation tool called Crank. And so I thought, great, Crank's connect to Flywheel. So I'll create a harness called Flywheel. And then within Flywheel, we'll have a class called Shaft, because Crank connects to the Shaft, which is on the... Anyway, so we have these silly names. We're running out of engine parts to call stuff, so it's not going to scale very well. So we have this thing called Flywheel. And if I run that up, what you'll see is it's a dashboard, essentially, that spits out real-time information about what's happening on the server, like how many messages are being sent through the message bus at the moment, and graphs sort of the number of sends and the average sends per second. So that's kind of cool. And then from here, I can control how many broadcasts I want to do. So obviously, there's no one connected to this at the moment, because it's just me. I haven't created any client load yet. So setting broadcast rate of 5 per second isn't really going to do an awful lot. But we'll see how we do that in just a moment. So I can set the broadcast size, I can set the broadcast rate, and I can say what I want to do when the Flywheel receives messages. So we also have in Flywheel something called Mini Crank. Let's try that again. Mini Crank. So Mini Crank is a page that connects to Flywheel, connects to Shaft, and then says, I can say go ahead and send a message every 100 milliseconds. So I'm now sending a message 10 times a second. And so what we should see now, if I say, well, on receive, I'm going to echo, we should see our send per second rate go up. You can see it did, because it's echoing back messages as it receives them. So that's kind of fun, but it's only one client, so that's really not that interesting. Mini Crank is really not very useful for doing load, it's just useful for testing that the harness works. What we need to generate load is a real load test generator. And so it's likely enough the IAS team builds one of those, it's called WCAT. Anyone used WCAT before? Okay, like three hands, let me quickly show you WCAT. So WCAT stands for the Web Capacity Analysis Tool. Great name. Let's make the X64. Make sure that most people are measuring and running 64-bit machines now. So when you search, make sure you search for X64, because the first page results otherwise won't show the 64-bit download. It's kind of strange. So you want to download WCAT 6.3 and install it. It'll just run on any Windows box. It's a native XE and some scripts that you can use to generate load, HTTP load. Now, so while this isn't a signal or client, I can make it do enough to make it generate load like a signal or client, or at least listen to signal or broadcast, which is all I really care for doing load testing. And so let's go back here and let's look at my WCAT setup. So this is all available as well. So we have a repository up on SignalR. So I didn't actually tell you where it was. Up on SignalR on GitHub. So here's github.com. So I go back up to SignalR. That was way too many SignalRs. There is a, here's Flywheel, which I just showed you, and here's Crank. And in Crank, we have a folder called WCAT, which contains all the settings files, which I'm about to show you, that you can use to generate load against SignalR using WCAT. So here's my WCAT folder. If I look in settings, most of this stuff is just copied from the WCAT samples and then tweaked. So I'm going to emulate 1,000 clients. So I'm going to have one physical client and then 1,000 virtual clients. So 1X year is going to be 1,000 people. So WCAT has the ability to have a controlling WCAT server and then multiple WCAT nodes. And then each WCAT node will be a client. So you can make that client 10 if you have 10 client machines. And then you can say each one of those client machines is going to emulate 1,000 virtual clients. And then that one WCAT server will control all the client machines. It's actually a really, really cool little tool. But I'm just doing this all in one box for the sake of a demo. So then I have a scenario file. So I have this shaft scenario file because I'm going to connect to shaft. And you can come down here and you can see that I'm going to connect to port 29573. And this is the URL I'm going to connect to to make it look like a signal receiving connection. So here's that connect phrase that we saw before when we looked at the network stack in Chrome. And I'm going to use the forever frame transport because it doesn't matter. I mean WCAT doesn't support WebSockets. So I just have to use either service end event or forever frame. So I use forever frame. And then I'm setting the connection ID to whatever the current virtual client index is. So vClient index is just a function provided by WCAT to get the current number of this virtual client. Okay. So I have a batch file that sort of runs all this together. So it runs the WCAT script with all the parameters that you need to make this thing run. WCAT isn't a user friendly tool. Let me just tell you that. It's quite finicky to get running. So it is well documented. It does have a fairly large word document, but it is a learning curve. So it's nice to be able just to get some scripts that work and then run it. All right. So we have, let's find my WCAT. There it is. So we have flywheel running. Let's see if it's still there. There it is. Okay. Let me pull that out. Let me pull that down there. Let's minimize that one. Let's put that up there. Let's come here. So currently I have no clients connected. You can see over here, no clients connected. Clients is zero. So let's start up WCAT. Okay. So WCAT is starting. So we can now see that connected clients are coming in. You see it's starting one virtual client every so many microseconds. So I'm going to go up to a thousand clients. So now it's sort of in its listening mode. It's still starting up clients. I'm going to get to a thousand. Okay. So now I'm going to start broadcasting. So let's broadcast at five messages a second. And what we should see is that I get about 5,000 cents per second because I have a thousand clients. I'm doing five broadcasts a second. So that's 5,000 cents per second going through the system. And indeed, so far, this machine is able to cope with that, without any problem. We don't start running into that contention limit that I talked about in our core of our architecture at the moment until you get to about 30,000 cents per second. And this machine wouldn't be able to handle 30,000 cents per second anyway. So you can see the CPU use, you know, is pretty high. It's actually, funnily enough, a lot of it is drawing this graph. If I look at the process, that's crazy, I know. If you look at the CPU, look, Chrome is using 38% of my CPU. So test, just a little lesson. Don't run everything on the same box when doing low testing. Don't run your dashboard on the same box as your server because drawing pretty graphs with Canvas on SVG takes a lot of CPU cycles on the browser. So you can see my web server, IAS, is actually only doing like 40%, 30 to 40%. And so it's actually the browser that's taking up most of the rest of the CPU at this time. So that's going to run for, I think, 90 seconds, is the test duration. So we'll just let that run because I want to show that what's going to happen when the test finishes as well. So you can see there's been no errors. WCat will keep spinning out all the stats every 10 seconds from the last 10 seconds. Now, because these connections never end, nothing comes out. Usually WCat just makes requests, and then as soon as the request comes back, it makes another request again. It's designed to generate load, right? But I'm using it to simulate persistent connections. So it just makes the connections, and then because I never end them, they just stay open. And WCat just sits there going, OK, connection's open. I'll just keep it open and just keep spinning out empty stats. WCat's fantastic because it has virtually no memory overhead. It's a native client. It happily receives everything I send to it from the server and then just throws it away again. It just uses no memory. It's fantastic. Incidentally, I did manage. I'm using a 32-byte payload here. On my infrastructure at home, I have a dedicated gigabit switch, and then I have a separate machine that I use to emulate the clients. And so when I ran that machine with 1,000 clients against my server through my dedicated gigabit switch with a 4K message size, I was able to saturate the gigabit nick on the client machine. So that's always a really, really good indication of your low test. If you can saturate the nick, that's good. That's really, really good. It means that your bottleneck isn't CPU or memory or anything else. So the test is finished now. You can see nothing is sending anymore. No one is connected. So if I scroll over, we should see I still have people who are connected. So remember I said there's the idea of a graceful disconnect and a non-graceful disconnect? So WCat finished, but it doesn't know to send that packet that signaler understands that the connection went away. So the connections were still alive on the server until such time that our background process came around and realized that they were dead. And you can see that that happened. So at this point here, our background process realized those connections were no longer there and would fire the disconnect event for all of those connections. So even though WCat weren't gracefully disconnect using a signaler, graceful disconnect, we came ahead and cleaned up those processes without any problem. So interesting point in terms of scale and RAM. I've talked about CPU and I've talked about connection. I've really talked about RAM. Where's my IS express process? Do it that way. Okay, so that's probably the one. I'm assuming the one that has all the memory. 100 meg. ASP.net has out of the gate about 40 to 50 kilobytes of managed heap size overhead per connection. I'm not going to lie to you. It's fairly heavy. So once we fix the sort of contention problem that we have in 0.5, which we'll fix in 0.6, your major limiting factor for scale is going to be memory. So we have actually driven signal up on a single box to 100,000 concurrent connections. And I think it used 40 gigabytes of virtual memory or something crazy like that. Because of this sort of limit in ASP.net. Now we are working on in 4.5, things have improved. And if you're using web sockets on 4.5 on Windows 8, that overhead is drastically decreased to like single digit kilobyte overhead per connection. And so it does get a lot better. But you can host signaler outside of ASP.net. Signaler is not an ASP.net library. It's a.net library. And we are host agnostic. The default setup when you new get in signaler is host on ASP.net. But you can host on whatever server you like. And indeed in 0.6, we're going to standardize on OWN as our hosting layer intrinsic. So if you want to host on a different server, like self-host using hdb sys, or a socket server like flywheel or kayak, which are open source C-sharp web servers, you can absolutely do that because we'll support OWN and those things support OWN. So you'll just be able to host signaler on top of whatever it is that you want. And there are people in the community who have already written custom signaler servers in order to do their own hosting from within their own XE. Now again, I think 99.99% of people who use signaler are going to use it in ASP.net and they'll never have to worry about that. But if you're going to be doing really, really high concurrency, lots of clients per machine sort of deployments, then a custom server might make sense if you're not going to be using WebSockets just because of the memory benefits that you'll get. You'll be able to support more connections per server, which is kind of cool. Okay, so we're nearly out of time. I've pretty much shown everything I wanted to show. So we have two minutes left for questions. Anyone have any questions? Yes? Mobile clients. What's that? Sorry? Mobile clients. Mobile clients. The question is mobile clients. Do we support them? Yes, we do. So if I go up to GitHub and we look at the repository, you'll note that we have a bunch of clients by default. So there is clients for Windows Phone 7, clients for Silverlight. The JavaScript client is just in the signaler library. There's a client for Windows 8, Metro apps. And there's a client for.NET itself. So if you're just using like a WPF app like I did that's an audit client. The community has contributed an iOS client. There's an iOS client that someone else maintains. There's a MonoTouch client that someone has built. There's a Java client I believe someone has built. Someone built a Node client. I have no idea why, because Socket.io is great. Use Socket.io if you're on Node, but they did. And I believe there's a MonoDroid client as well available. Now, our current thoughts for version one of SignalR is we would like to have all those clients sort of built by the team and supported. Because we think SignalR is much more attractive the more clients it has. So look to see, ask, pull those clients in or build new versions of those clients for version one whenever they get down. Any other questions? Yes? So the question was what about T4 templating instead of generating the script dynamically? So one of the problems with generating the hub proxy at runtime is you don't get IntelliSense on the hub in Visual Studio. It's kind of nice in JavaScript if you can get that. We do have some prototypes of that and it is on our backlog to support design time slash compile time generation of that file so that you'll get IntelliSense. I do believe actually something has already checked in that does that. I'm not sure that it uses T4. I think at the moment it uses an XE so that you can just run that from inside your build file so that it'll just build the JavaScript file and jump it into your project. And you'll just reference that JavaScript file rather than that magic route that I showed you before. So yes, we are working on that. Yes? I've seen on iCat for instance you get the constant loader. Yeah. Is that something you know? So the question is on some clients with some of the transports you get the little loader spinny to stays there forever. It's a registered issue. We're looking at it. The current fix that we have that we're testing out is just to delay the creation of the transport with a set timeout. So rather than doing it immediately just say set timeout 250 milliseconds and then create it and that seems to fool the browser enough. It seems crazy that a browser would support service end events and then show the spinny while the thing is open but they do. Some of them, iOS in particular. So we are going to fix it. Yes? Yep. Right. So I think, let me rephrase, the question was about graceful disconnect and IE and IAS and about what combination is required to support the graceful disconnect? Right. So IAS has this ability to asynchronously notify your code when a client disconnects, which is nice. Now that's not graceful disconnect. Graceful disconnect in a signal our terms is when the signal our client tells the server I'm about to stop the connection. So any browser that will run our code on window unload and let that Ajax request go through will support graceful disconnect because then we'll just receive an Ajax request on the server that is a disconnect command and then we'll disconnect the client in our server. If that doesn't get received and there's a couple different ways that we can detect the client is disconnected. IAS 7 and above gives us this is the, IAS 6 and above gets us this is client disconnected property on the response object that we can essentially poll. So every 20 seconds we check the connection and say is client disconnected false? Oh it is. So the client is now gone. Let's see if it's over the disconnect threshold and then we'll disconnect them. In ASP.net 4.5 we've added if you went and saw my talk this morning there is a new asynchronous notification you can subscribe to to get told when the client goes away because IAS 7.5 or above supports this and so if you're using ASP.net 4.5 on IAS 7.5 you'll be able to subscribe to a cancellation token on the request object that will fire when the client shuts down or closes the connection. Assuming that that gets to you know because underlying the TCP level connection there will be a message sent up to the server and IAS will bubble that up asynchronously to your code. So we do our best whether it's graceful or disgraceful, no that's not right, graceful or not disconnect to try and notify your code that a client has gone and do it in the most timely manner that we can and try and ensure that we only do it once. That was a big problem in disconnecting web farms that we didn't fix until 0.5 is how do you handle the fact where I connect to server 1 and then I reconnect to server 2 now server 1 is going to fire a disconnect event. So we had to handle we have to have cross node collaborations such that when you connect to server 2 server 2 can tell all the other servers hey I now own connection 1, 2, 3, 4 everyone else just forget about it don't fire the disconnect event. So that's what we added in 0.5 to make disconnect work in web farms properly. So I'm out of time but I'm happy to keep answering questions while people are still here because it's 15 minutes until the next guy so. Oh actually it's only the party now so I'm just keeping you from drinking so if you want to know more I can do that but thanks for coming along and try it out.
 I am losing my voice, but I will do my best to get through this next hour for you.  I'm a program manager on the ASP.net team at Microsoft,  but today I'm going to be talking about a project that me and another guy on the ASP.net team,  David Fowler, started in our own time last year called Signalar.  Signalar is a persistent connection abstraction for.NET.  So how many people have heard of Socket.io on Node?  Okay, a few people, almost everybody, which is good.  So Signalar is kind of like Socket.io for.NET,  but we also have elements of Now.js, which is another library for Node  that builds on top of Socket.io in Signalar as well.  But again, it's all for.NET.  And so if you're using Node already for real-time stuff, that's fantastic.  Socket.io is a fantastic library.  I'm not here to tell you that we're better than Node or anything.  I'll leave that to tomorrow in the cage match with Rob Connery.  But if you're a.NET developer and you want to do real-time development,  then Signalar, I would hope, is something that you want to have a look at.  So without further ado, I don't have any slides.  I really don't like using slides these days because most of the talks I do are full of code.  So let's just write some code and we'll learn how this thing works.  So I'm going to start a new empty web application.  And then I'm going to sort of new get in the world.  So I'm going to say manage new get packages.  And then from a local feed, I'm going to install Signalar.sample.  So we have this working sample package for Signalar, if my machine is there.  So here we go.  That you can pull into your project.  It pulls in all the required dependencies, obviously,  that are needed to get Signalar itself working.  And it pulls in some working code.  So we can see here we have the beginnings of a stock ticker.  Now, this is not a real stock ticker that connects to some service in the cloud.  It's just some background thread that gets kicked off and fakes out of stock market.  But it's a good indication.  It's a good sort of learning tool to see how something might work.  So let me go ahead and run that up.  We can see that I've got that running over in one browser.  I'm going to launch another instance and put that over here  because real-time demos are always that much more impressive than we have two browsers.  So hit me open market and you'll see that the changes are synchronized on both sides  because we have two browsers connected to the same Signalar endpoint on the server  and receiving information from the server and updating the UI as appropriate.  So obviously in this case the client is JavaScript.  We do support multiple clients and we'll talk about that later on.  And the server, of course, is.NET.  And I can go and hit close market here and you see it synchronizes on both sides.  So while the majority of this is the server pushing to the client,  when I click a button, obviously the client is pushing a message to the server  and then that's resulting in the UI changing in both of the connected clients.  So that's great, but let's go ahead and build something from scratch.  That's perhaps a little bit simpler so that we can get an idea of what this looks like.  So I'm going to add a new folder and we'll call it move shape.  And inside this folder I'm going to add a class  and I'm going to build my server-side logic for my move shape application.  So I'm going to call this the move shape hub.  So we have two levels of API server-side in Signalar.  We have a low-level connection API, which is very similar to Socket.io.  It is literally mimics a socket.  So you open a connection, then you can send messages on it and you receive messages on it.  You get an event when someone connects and you get an event when someone disconnects.  And that's about it.  So if all you care about is sort of the raw socket level stuff,  you can program at that API and good luck to you.  But most people like to use what we call hubs.  We have this higher-level API called hubs,  which lets me do reverse sort of procedure invocation from the server to the client.  And vice versa, obviously the client can call the server.  So I'm going to go ahead and create a hub.  I'm going to derive from hub.  I'm going to decorate this with an attribute that lets me change the hub name on the client.  So I'm going to call it move shape on the client,  because I like this word hub appearing there.  I'm going to say public void, move shape.  I'm going to take in an x and a y from my client.  And whenever that happens, I'm going to go and tell the world that someone has moved a shape.  And the way I do that is by accessing this client's member.  And if I sort of zoom in here and have a look at clients, what you'll note is clients is dynamic.  So clients has a property on hub,  and clients represents all the people who are currently connected to this hub via signaler.  And I can now go ahead and invoke a method in my client from my server-side code.  Now that client might be JavaScript, it might be a.NET client, it might be iOS, it might be Monotouch.  But in this case, it's going to be JavaScript.  So this is dynamic, because obviously this isn't.NET code that's going to be running here.  This is going to be something that's sent over the wire and invoked on the client.  So I'm going to say shape moved, and I'm going to pass in the current connection ID.  So that's going to be context.connectionID, so that they know who did it.  And then the x and the y that was passed through.  So that's my server code done.  Let's add some client-side code.  So I'm going to have JavaScript file, move shape.  Now I need to pull in another library here, so I'm going to go back to newget, go to my Dropbox feed.  I'm going to look for jQueryUI, install that.  Wait a moment, pause for dramatic effect, there we go.  I'm going to drag in jQuery, drag in jQueryUI,  and I'm going to start writing some signaler client code.  Actually I may as well drag in signaler in here as well.  This is just for IntelliSense reasons.  So I'm going to go ahead and get my hub.  So that's dollar.connection.moveShape.  We'll talk a little bit more about how that turned up in just a moment.  And I'm going to have some type of UI on the screen that people can move around.  So let's just say it's going to be an element called shape.  So let's go ahead and find that.  Okay, so now that I have my client-side hub, moveShape, I have to add that method that I want to be invoked.  So if we go back here, we saw that I'm going to invoke a method called shapeMove.  So let's add that method.  I'm going to use jQuery's awesome extend method to do that.  So for those of you who haven't used extend before, all it does is say take the object here  and add anything that's on the second object to the first object.  So I'm going to add a method called shapeMove.  And that method has to take a number of parameters from the server.  So connection ID, x and y.  If we go back to here, you can see I'm passing connection ID, x and y.  So I have a matching method signature on the client.  And then I'm going to check to see that this wasn't invoked by myself.  Because I'm going to be listening to all messages.  And when I broadcast something to, when I send something to the server,  I'm going to get that same message back again.  So I'm just going to do a little check here to make sure that this isn't a message that originated from me.  So I'm going to say if dollar.connection.hub.id is not equal to connection ID.  So it's not from me that I want to go ahead and move the shape on the screen to this new position.  So I'm going to say dollar.shapescss.  Left is equal to x and y is equal to top.  Oops, get my bracing right.  Okay, so now that I have my client side method,  I need to go ahead and wire up the client side logic  and then call the server whenever I move this shape on the screen.  It should be top equals y, I think, very much.  And I've already got my first correction from the crowd.  Fantastic, price for you, sir.  Left, x.  So now I have to go ahead and wire up the client.  So first I need to go ahead and start the connection.  So I'm going to say dollar.connection.hub.start.  And then when that's done, I'm going to pass in a callback here that will get invoked once my connection has actually started.  I want to go ahead and enable the sort of dragging behavior so this can get moved around.  So I'm going to say shape.dragable, which is that jQuery UI function that I brought in.  And I say when that gets dragged, go ahead and invoke this function.  And when that's dragged, I want to call the server and tell the server,  hey, what's the position of the shape?  So I'm going to say hub.moveShape.  So again, moveShape is this method here on the server.  So this is my hub.  I'm going to call hub.moveShape.  And I have to pass in x and y.  So that's just this.offsetLeft, this.offsetTop.  Like so.  Okay, so that's my client-side code done.  Let's add a page to actually show it on.  Let's add all these JavaScript packages that I need.  So I need that one, I need that one, I need that one.  Let's drag those into here.  And I need to add an extra magic script reference that we'll look at in just a moment.  That's going to pull down some dynamically generated JavaScript to make this sort of signal magic happen.  So signalr slash hobs.  I'm going to add my div with an ID of shape.  And so that you can actually see my shape, let's add a style block.  And we'll say shape.  Width is 100 pixels.  Height is 100 pixels.  And background color is some new...  Let's have a look.  This time blue over here looks pretty good.  Okay, so that's my app.  Let's run that up, see if I made any mistakes.  Okay, so it's showing there, that's a good start.  Let's open another browser instance, put that over here.  Paste that in there.  And if I pick this up and move it, you can see that it moves in both sides.  So really, really easy to get going with signalr doing these type of broadcast scenarios.  So let's tease apart this demo a little bit now and try and get an understanding of why this even works and what's going on under the covers.  Okay, so let's have a look.  Let's bring up the network tab here and we'll hit F5.  We'll see a few things that happen when zooming down here.  So as Remember I said, signalr is an abstraction.  It's an abstraction over various ways that we can in HTTP mimic or actually achieve a full persistent connection between the client and the server.  So how many people have heard of WebSockets?  Everybody.  Okay, good. WebSockets is kind of synonymous with this new move to the real-time web.  The problem with WebSockets is they don't work.  They might work if you have a browser that supports them.  If you're a.NET developer, they'll work in ASP.NET if you have Windows 8 on your server and using.NET 4.5.  They'll work if your hosting provider supports WebSockets through their reverse proxy and load balancing infrastructure.  And if your client is behind a firewall or a proxy that also won't trample on WebSockets.  If all of those things are true, then yes, you'll get a WebSocket connection from your client to your server.  Now, we know all those things aren't going to be true for quite some time yet for the vast majority of people.  And so libraries like SignalR and Socket.io exist to help us bridge that gap.  What do we use when WebSockets isn't available?  They also give us a much nicer, higher-level API.  Who's actually programmed with WebSockets?  Okay, only a couple of people.  It's hard. WebSockets is sockets.  So you don't get any of the niceties I just showed you.  It's open a socket, send a message.  So you have to do all your own dispatching.  You have to do your own invocation logic.  It's basically just sending strings or binary data back and forth.  If you've ever done socket programming before with raw sockets, it's basically similar.  And the server-side programming, and that's just the client side, the server-side programming is even harder.  There's a specific way you have to do WebSocket framing.  You have to ensure that messages are sent in order.  You have to ensure that you're only ever sending one message at a time on a connection.  So there's all these types of buffering and synchronization code that you have to write if you're not using a framework that does that for you.  So it's nice to have a high-level framework so that I don't have to worry about that type of stuff.  So if I don't have WebSockets, what can I use?  So we fall back to a number of different things.  So if we come down to this request down here, you can see that there's a request to an endpoint called Negotiate.  So the first thing that SignalR will do is make a standard Ajax call to the server saying,  hey, I need to negotiate a transport.  I need to figure out what can I use for me, client, to talk to you, server, in somewhat of a real-time fashion.  Now, we'll start out with WebSockets, and then we fall back from there.  Now, we'll only attempt to use WebSockets if the server says it can support WebSockets.  If you're running on top of ASP.NET, that means you're on ASP.NET 4.5 on Windows 8 with IIS Express 8 or IIS Express 8.  Now, most people aren't there yet, so most of the time you're not going to be using WebSockets just yet.  You'll then fall down to something called Server-Send Events or Event Source.  Server-Send Events is a technique or actually an API that you can use in the browser in all browsers except IE.  That lets you have a persistent connection from the server to the client such that the server can push information down to the client.  So if WebSockets isn't available, we'll try and use Event Source.  That will generally work in all browsers except for IE.  So we skipped Event Source for IE, and then we go down to the next level, which is Forever Frame.  Anyone ever tried using Forever Frame? Ever heard of that technique? A couple of hands go up.  So Forever Frame is the idea of having an iframe embedded in your document that makes a request, loads of document from the server,  and all that document in the iframe does is spit out script tags, and it never finishes.  So it's just an ever-growing document full of script tags, and the great thing about browsers is that they'll execute script tags as they get them,  even before the page is finished loading.  So you can have a hidden iframe with a document in it that gets script tags that contain the messages that you want to be sent to the client,  and it'll happily keep invoking them for you.  So Forever Frame will be used generally in IE because it supports Forever Frame quite well.  And then if none of those things are supported, which is unusual, but it can happen depending on the infrastructure between the client and the server,  perhaps the router or something doesn't like a persistent HTTP connection, then we fall back to the lowest level, which is long polling.  So the idea of long polling, when we all know what polling is, right, polling is, I call the server, have you got data?  It replies no.  So I say, okay, after some period of time, I call the server again.  Do you have data now? No.  So I wait a little bit longer, and they say, hey, have you got data now? Yes.  Okay, so now I have data, and then I wait a little bit more, and then I poll.  Long polling is the idea of saying, let me call the server and say, have you got data?  And the server doesn't return until it does.  And so that connection stays open until there is data available to sort of fill that request.  And then once that request comes back, I process it on the client, and then I send immediately another request saying, hey, have you got any more data?  And then that stays open until there is more data.  So long polling is advantage over polling in that while there is no data flowing, you have an open connection,  but you're not really using any resources other than those taken up by an open connection.  You're not constantly hitting the server with a request that doesn't result in any data, which is kind of nice.  It also has very low latency compared to polling because you're going to get the data as soon as the data is available,  assuming you have a connection open.  So we had a negotiate request, and after that we had a connect request.  And if we look at the URL for this, zoom out a little bit, we can see that over here, we have signalize slash connect.  So now that I've done my negotiation, I'm going to connect to the server with the connect verb.  I'm going to say transport equals server-cent events.  So the client and the server negotiated server-cent events because WebSockets wasn't available.  And then server-cent events, as I said, is this one that Chrome, Firefox, Opera, Safari support.  And then once that's open, what we'll see is that thing stays open.  So we should see over here, here's that server-cent events message over there.  You can see it's been over open for two minutes, been receiving for two minutes.  And if I come over and open another browser now, let's do this one over here, so let's push this one back.  And if I move this around, we'll see that that bar changes if it doesn't make a lot of me.  Let's see if I can make this a little bit easier to see.  It might be easier if I just refresh.  There we go.  So here's my connect down here.  As I move this around, see how that gets longer because it's currently receiving information from the server  so that load time for that request just keeps getting longer and longer and longer.  And that request will just stay open while it's receiving data until either the timeout kicks in.  So there's a default timeout of two minutes at which point it'll reconnect or something goes wrong, obviously.  Okay, so that's sort of the intrinsics of negotiation, negotiated transport, and then get a connection as a result of that.  So what else happened in that negotiate request?  Because there's other interesting things that happen in here.  We zoom into here and have a look at what was returned.  So we get a JSON payload back from the server when we negotiate, which gives us a URL, and we get a connection ID.  So that's interesting.  We know that every connection that connects to Signaler gets a unique connection ID.  Now, in this case, it's a GUID.  You don't really have to worry about it.  We'll have a look a little bit later on when you'd need to worry about mapping this connection to something useful.  But this means that you can address people individually using Signaler because you have a connection ID through which you can identify them, which is kind of cool.  You can also see that we sent back a flag saying whether we should try WebSockets.  So on the server, we determined whether WebSockets was even going to be supported.  And if it wasn't, we tell the client, don't even bother trying because it's not going to work.  Okay.  So that was a very, very simple demo.  Let's move on to something a little bit more convoluted.  We do support something, we do support more clients than just JavaScript.  So let's open up a slightly more complete version of this application.  Let me go ahead and find it.  And let's open this one here.  So this is the same demo that we just saw.  It's move shape.  It has move shape.  It's basically the same thing that I just showed you.  It's just a little bit more UI and a little bit more logic in the client.  But other than that, it's the same.  So if I run it up, you can see here it's pretty much the same as we had before.  And now I'm telling you how many clients are currently connected as well.  So I've got this number in the top right-hand corner.  So how many people are currently connected?  So what we also have here, though, is a different sort of client.  I have a WPF client.  So I'm going to come in here.  I'm going to show up this move shape desktop.  Come back and open this one.  Let me pin this to the right.  And now when I move this around, you'll see that I've got my WPF client also receiving this information from the right-hand side.  And similarly, I can move from the left to the right.  So the code for this looks pretty similar.  Let's go back and have a look.  So let's have a look at my...  I'm not the greatest WPF programmer in the world,  but I can sort of model my way through it.  So it's just a canvas with a shape inside of it  and a text block for the number of clients.  And then the code behind for this canvas is...  I have an async void method go  because SignalR is async from top to bottom.  In order to scale in ASP.NET, it needs to be asynchronous.  If you're going to keep connections open for a long period of time,  they have to be asynchronous because you don't want to be using a thread  when that connection is doing nothing  because you're just going to run out of threads  and then your server won't be able to serve any more connections.  And so SignalR is async top to bottom, both on the client and the server.  And so you can see I go ahead and it looks kind of similar to the JavaScript code.  I knew up a hub connection.  I go ahead and create a proxy for that hub connection.  Now in JavaScript, that was done for me automatically.  I'll go back in a minute and show you how that happened.  But when I imported that JavaScript slash SignalR slash hubs,  that was a hub proxy being created for me.  So I have to create it manually over here in.NET world.  And then rather than doing method invocation,  I'm handling method events.  So I'm saying when the hub raises an event called shape moved,  go ahead and invoke this delegate using these strongly typed parameters.  So connection ID XY.  And look very, very, again, very similar to what we had in JavaScript.  Although now it looks like WPF.  I check if it wasn't myself and then if it wasn't,  I go ahead and invoke this delegate back on the UI thread  to go ahead and move the shape on the canvas.  And now that I'm also tracking connected clients,  I get a message whenever that client count changes.  So when I connected and I got two clients, I got a message  and I go and invoke that as well.  Then I go ahead and start the connection.  And I await that because it's asynchronous.  And then once that's finished, I go ahead and enable the draggable UI.  Now this draggable is just my own sort of ghetto extension  for WPF that makes something draggable on a canvas.  So don't worry too much about that.  I've just sort of emulated what jQuery UI does.  So I've said it's draggable and then when anyone drags it,  go ahead and invoke this lambda and tell the hub to invoke the move shape method  and set the left and top based to what this is here.  So kind of the same stuff.  So there is an interesting thing that was different on the server though.  Let's have a look at that.  So move shape.  So here's my hub, very similar to the one we had before.  But I've got two interfaces that I'm implementing this time that I wasn't before.  I connected and I disconnect.  So signal as a connection abstraction gives you connect and disconnect semantics.  And so you can get alerted whenever someone connects to your hub or your connection  and alerted when they disconnect as well.  And so for a hub, the way to do that is to implement these two interfaces.  I connected and I disconnect.  And then we will invoke your connect method whenever someone connects to the hub  and we'll invoke your disconnect method whenever someone disconnects from the hub.  Now we also have a reconnect intrinsic, which you can handle as well if you want to.  And that can be useful to ensure that when clients reconnect,  they are going to say that they're a member of a period of groups  and you can check whether that's actually true.  So I'll talk about that a little bit more in a minute.  So the interesting thing here is that I'm showing how you can go ahead and track connections.  So one of the questions we very often get when talking about SignalR is,  how do I get a list of clients?  And the answer is you don't, because there is no list of clients.  SignalR at its core is built on a PubSub mechanism.  In order to enable scale out, which we're going to look at a little bit later,  we don't store state.  So if we were able to give you a list of clients,  it would be very difficult for us to scale that out in a web farm  because obviously you can have a thousand clients connected to one server  and a thousand clients connected to another.  And if your code is running on the second server and says,  give me a list of clients, how does it know what clients are connected to the first server?  Unless you're sharing some sort of back end state.  And so there is no list of clients.  What you have is a list of signals, not even a list,  just arbitrary keys, arbitrary signals that you can broadcast to at its very, very core.  Every client gets its own signal, that's what that connection ID is.  Every endpoint gets its own signal.  So this move shape hub will have a signal called move shape hub.  And whenever you send a message to move shape hub,  we literally send a message through the message bar that says,  broadcast to move shape hub this payload.  And the payload for hubs will include what method it is that you want to invoke  and the arguments that you want to pass to that method.  And so it's up to you to track connections and who exists on what connection.  So in this case, I just have a static concurrent dictionary,  because this is asynchronous.  I could have multiple threads operating on this hub at one time,  so I have to have a concurrent dictionary of connections because it's static.  And then whenever connect is called, I go ahead and just add a record to that concurrent dictionary  keyed by the connection ID.  And then I go ahead and broadcast out to all clients the current counter to that dictionary.  So I'm just using this dictionary as a way to track how many people there currently are in my app.  Now, obviously, this wouldn't scale out because it's a static in-memory dictionary on this class.  But you can imagine in a proper application, this would be stored in a database  or in some type of distributed cache so that you could actually do proper  how many people are currently connected sort of intrinsics.  So similarly on disconnect, I go ahead and try to remove that  and I now update the counter appropriately.  Now, what isn't shown here, which is interesting to note,  is that the relationship from users to connections is one to many.  So if you have the concept of authentication in your application,  then obviously people will log in using some type of credential  and then they have some type of username, so it might be Damian in my case.  And then when I use SignalR, I'm logged into your app as Damian,  and then I'm going to connect to your app with a connection  and that connection has a connection ID.  So I need to store somewhere the fact that Damian is currently on connection 1, 2, 3, 4.  And so that should be persisted away in your database or persistent mechanism  so that when someone says, hey, I want to broadcast a message to Damian,  you can look up the connection ID that Damian is currently on  and then send a message to that connection ID.  Now, I did say it was one to many though.  I mean, I can obviously open more than one browser,  or I can open a browser and iOS app or a Windows phone app  and connect to the same thing with the same user,  but I'll have different SignalR connections.  So the recommended practice is to ensure that you're storing one user to multiple connections.  Now, for a good example of how this works, we have sort of our smoke test app up in the cloud,  this chat app called Jabba.  So Jabba is sort of an IRC clone written on top of SignalR.  It's hosted up on Windows Azure, but that's kind of incidental.  And it's the sources available in GitHub,  so you can go and see what it's like to build an ASP.NET application of this nature  that's real-time using SignalR.  And this uses SQL Server, it's underlying persistence mechanism,  so you can see how all the user names are persisted,  how the user names are mapped to individual connections,  how we handle connect and disconnect.  You can see as I'm talking here, people are typing  and we're getting little speech bubbles that come up when they're typing,  so it's more than just messages flowing back and forth.  We actually have things like status indications as well.  Jabba has some really interesting stuff as well.  It has content providers, so if I keep scrolling up here,  I should be able to find an example where someone has posted a JPEG, like so,  and then we have sort of built-in content providers  that will then go down and pull down that JPEG  and throw it in the room for you, which is kind of cool.  So it's a really nice application for learning the type of things you can do with SignalR  and what you can do with real-time.  So, well worth pointing out.  It does get a little bit wacky in general chat sometimes,  so I tend to stick into the more focused rooms, so to say.  Okay, so let's go back to the JavaScript client for a moment  because I talked about this creation of the proxy that I didn't really elaborate on.  So if we go back to my index, we can see this SignalR slash hubs request  that I put in here as a JavaScript file.  Let's have a look at what that actually is.  So let's bring up my network stack again.  It's at F5. Let's find that one in here.  So here it is, SignalR slash hubs.  So we can see what we pulled down was a JavaScript file,  but this JavaScript file was dynamically generated on the server.  And if we scroll down, there's a whole bunch of wire-up stuff which is interesting,  but not what I really care about.  What we'll see down here is this part.  This call to $.extendSignalR with myHubs.  And so you can see MoveShape was my class, my C-sharp class on the server  got turned into this JavaScript object that has a method that I can invoke  that goes ahead and calls this server call function to actually make the call on the server.  So it kind of appears like magic, but really all that we're doing is generating some JavaScript.  It's really generating a proxy, just like you would have done back in the old days  when you added an Asmx reference or WCF reference using Add Service Reference in Visual Studio.  And then it would generate you a JavaScript proxy if you added it to the script manager in webforms.  It's kind of similar except we do it at runtime.  And we also allow the server to call back into the client.  And so we get this really, really nice sort of back-and-forward remote procedure call paradigm  that we can do between the client and the server, which is kind of cool.  Okay, so that's how that works.  Let's have a look at some other interesting things.  So WebSockets.  So I said that WebSockets wasn't running in this demo and it isn't.  So the version of SignalR that's available up in Nuget right now is 0.5.0.  The next version, 0.5.1, will come with WebSockets support in the box.  So I actually have the source application open right here  so we can have a look at what WebSockets support looks like just to prove to you that it does work.  So it does require Windows 8 on the server, so I'm running Windows 8 Release Preview here.  I'm running Visual Studio 2012.  Oops, that's a known problem.  Let's go back and close that and try that again.  Rebuild.  I'm running Visual Studio 2012 RC, which comes with IS Express 8.  And so because I'm running IS Express 8 on top of Windows 8, I get WebSockets.  So if I F12 in here and I hit F5, what we'll see down here is a different sort of request.  So I'm in a browser that supports WebSockets.  I'm in Chrome.  And we can see the negotiate happened.  If we look at the negotiate this time, we can see that Try WebSockets is true.  So we're going to get an attempt for WebSockets, which is good.  And I get this, Connect Raw.  We can see that the URL there says transport equals WebSockets.  And then you can see the status from the server was 101 switching protocols.  So this is how WebSockets works.  WebSockets is an upgrade request.  A standard request is made to the server.  It's a get request.  You can see that here, get.  And then it says in there, there is a header that says, hey, I want to upgrade this request to a WebSocket request.  And then if the server replies with the 101, that means, yes, party on, we now have a WebSocket.  We can now do persistent connection.  And so we won't see any other, if I go ahead and start broadcasting stuff now, there are no other requests happening  because I have a WebSocket.  This thing is just there happening underneath the covers now.  Now, I do have Chrome Canary installed here.  And in theory, ooh, okay, see what that does.  Chrome Canary is supposed to give me WebSocket inspection capabilities.  Let's have a look at this works.  I've actually tried this.  I'm going off script here.  So let's go network.  Let's F5.  Here it is.  There's my WebSocket.  And if I go to here and I go to WebSocket, look at that.  There's my WebSocket frame.  Sweet.  So if I broadcast stuff and I come back to here, there's the WebSocket frame.  So you can actually see the messages flowing over the WebSocket.  And it even shows you the direction.  So this is saying coming from the server, that right to left.  And this is the JSON payload that Signaler was sending back from the server to the client.  So you may have noticed that Signaler has its own protocol.  You connect to a Signaler server with a Signaler client.  It's much like Socket.io.  This is our JSON protocol.  So we wrap whatever message that you send, which is we serialize whatever you send as  JSON, you can just send random.net objects.  We'll serialize them with JSON.  And then we wrap that with sort of a message framing protocol, which itself is JSON as well.  And so that's what you'll see flowing over the wire.  So that's kind of cool.  We've got WebSockets running there, which is nice.  So we have some other samples in our sort of sample project that's up in source.  That's my daughter, Elizabeth.  That was raw connection that I just showed you there.  We have an example of just streaming.  So in this case, all we have is there's a background thread on the server that is just pumping messages to the client.  So rather than any type of interactivity, I just have a dumb client that's just listening passively to messages.  A bit similar to the stock ticker sample I showed you originally.  We have this mouse tracking one, which is kind of cool.  So every person who connects gets a cursor and with a little number on it.  And you can see that update in real time, which is kind of nice.  We had that up to some ridiculous number and it does get a little bit strange after you've got dozens and dozens or even hundreds of people in there.  We have this one called ShapeShare, which is sort of a more advanced version of the MoveShape demo I showed you.  So I can put this one, I can actually add a username in here.  So I have left, right, and then I can add a rectangle and I can move that round and I can add a picture.  And I can move that round and I can sort of resize that.  And you can see that it says change by right.  And if I move it, it says change by right over here.  It says change by left.  So the source for that one is quite interesting because it shows mapping usernames to connection IDs.  So that one is worth checking out when you go and get latest from GitHub.  And then we have a drawing pad.  Someone contributed this one.  So this is using Canvas to go ahead and do sort of multiple people drawing in the same pad at the same time, which is kind of nice.  And we have chat, but chat is basically what turned into Java.  So I'm not going to bother showing that.  So connection status is interesting.  So I talked about the fact that we do connection intrinsics for you.  We manage connect and disconnect.  We also have the concept of reconnect.  So some of these transports aren't truly persistent.  So WebSockets is a persistent connection.  It's bidirectional, it's open.  You can send stuff both ways and it stays open.  But all of the other transports aren't actually full duplex.  Service and events in Forever Frame will keep a connection open over which the server can send stuff to the client.  But the client, when it sends to the server, it just makes an Ajax post.  And we sort of hide all that under the layers for you.  So what happens when the underlying receive channel goes away?  I mean, it's the internet.  Sometimes things go bad.  So we have built-in retry logic.  So if the connection goes down for whatever reason, we'll reconnect and we'll continue trying to reconnect until the server comes back up again.  Now, by default, well, until last night, I was just looking at the check-ins and we've actually changed this behavior,  we used to have, we do have the concept of a time-out, so you can actually set a value that says,  keep the receive channel open for this amount of time and then forcibly close it, forcing the client to reconnect.  That can be useful in certain situations, depending on what your load balancing infrastructure is like.  But now we actually have the idea of Keep Alive.  So by default now, from source anyway, not in 0.50, but in 5.1, we have a Keep Alive packet that will be sent.  So while that connection is open, we will ping from server to client an empty payload just to keep the connection open.  And that will trick load balances like those used in Azure and App Harbour and those type of things to not terminate the TCP connection.  Because what we find is that a lot of hosting companies, their infrastructure for sort of handling connections,  if they see a connection that isn't doing anything for a period of time, they'll just abort it.  And so you have to be able to keep sending information over that, like a heartbeat ping, to keep that connection open.  So we do that for you by default now in 0.5.1, which will be out very shortly.  So because we have Keep Alive now, this actually won't drop. This will actually stay open.  What you would see is if it reconnected, if it did drop, we'll go ahead and reconnect for you.  And we will raise that event to your code so you can handle reconnect if you want to, but most of the time you don't have to worry about it.  The thing will just reconnect. And you can see here that as soon as I disconnected on this side, I got the red saying that I left.  So we handled that disconnect for you as well. Disconnect is a really, really interesting issue.  Detecting when someone disconnects from your web server is actually really, really difficult, because there is a lot of different ways people can disconnect.  So the reason that worked so well this time is we recently added support for graceful disconnect.  So when we actually listen to the events in the browsers that support them that say the person is navigating away from this page, like the window on Unload,  and if it does, we will try and send a packet to the server saying this connection is about to be closed.  Because if you hit F5, what you're basically doing is killing one connection and then reopening another one.  Connections don't last beyond pages, of course, because they only open as long as that JavaScript is running.  And so when I navigated away from that page, you can see that I got disconnected on the left-hand side because we sent a packet to the server saying I disconnected.  If for some reason that packet wasn't able to reach the server, then we have a background thread that runs on your application on the server that does know about all the connections for that server,  because you might be running in a web farm, and will every 20 seconds or so check every single one of those connections and see whether the client is still connected.  So IIS does have the concept of is client connected? There's a property on the response object. You can check if the client is still connected.  And if that's false, then we look at some threshold, and if you're over the sort of the disconnect threshold, then we'll go ahead and fire the disconnect event,  raise that up to your code, and you'll be able to do whatever it is that makes sense in your application for when you use the disconnects.  Now, when talking about reconnect, that kind of suggests that there's a period where connections aren't open.  And so what happens if messages are sent to the user while your underlying connection isn't actually open?  It's a little bit hard to demonstrate, but you can imagine here that, let's see if I can actually demonstrate this.  Let's see if I can put a break point. So the server is sending messages, and we can see on the left-hand side the one that isn't going to get broken here.  So I'm going to come over to my...where is it? I'm going to come over to...resources, thank you.  No, that's not what I wanted to...  I'm in Canary, which is what's making this difficult. It looks like it's different. Let's come over to here.  Okay, scripts is what I wanted. Let's come over to SignalR.  So we can see this one. Let me just shift these around so I can see them a bit better.  So the one over the left is going to keep running.  Drag...no...oh, this is not looking good. Let's try that again.  Where is that?  Ah, now I've lost it completely. That one is that one. Let's put that one there. That one is that one.  Okay, let's pull that one off. There we go. Put that one over there.  Okay, so what we want to do is find the transport logic that's going to handle events.  So here's service and events. I know that's what I'm using.  I'm actually using WebSockets to process messages.  Transport...da, da, da, da, da. Here we go. So I'm going to put a break point here.  Okay, so I'm broken.  And so over here, you can see the left-hand side is still getting messages.  And the right-hand side isn't. Well, you can't scroll, but you can assume that it's not.  And now if I hit play and I get rid of that break point, we'll see that I didn't miss any messages.  I got all the same number of messages. So you can see 21, 23, 25, 27, 29, 31, 33, 35.  It goes up by two every single time. I didn't miss any messages, even though that connection wasn't open  at the point that those messages were coming through from the server.  And that's because on the server, we buffer messages.  So we have an in-memory buffer so that while connections are in their sort of their reconnect phase,  where they're trying to reconnect again, we'll store those messages in memory.  And then when the connection reconnects, it always says, hey, give me every message since message 47.  Because that's the last one I got. And then if the message is since then, we'll send those messages down  and the connection will go in its merry way. So that's how we handle reconnect, which is kind of nice.  Okay. Scale out. So one of the questions that most people ask, first questions that most people ask,  is usually two. How does it scale? Like, how many connections can you support? And how do you do scale out?  Well, I'm glad you asked. Let's have a look at that.  So we built SignalR with the ability to scale out in mind from the very, very beginning.  So that's why we don't store state, like a list of connections which we enumerate over to do stuff.  What we do do is base things on a PubSub mechanism.  And so all you need to do is have some type of message backplane across your web farm that you can use  so that if you've got one server here, another server here, you've got 100 people connected to this server  and 100 people connected to that server, if I broadcast from server one, I want to make sure that all the people on server two  get that message as well. You need to have some type of common backplane for that to work.  And we currently ship two backplanes that we support. One is Redis. So who's used Redis at all, anyone?  Oh, no one has used Redis. Wow. Is everyone here a.NET programmer, I'm guessing?  Yes, that's why you've not used Redis. So Redis is an in-memory database that's very popular in sort of the Linux world.  But MS Open Tech, the new open source subsidiary of Microsoft, has released as its first open source project a port of Redis for Windows.  So we have a Redis provider for SignalR to do scale out and we have an Azure service bus provider.  So if you're deploying SignalR in Azure with multiple nodes, you can plug it into Azure service bus as the backplane for the messages between your nodes.  So let's use Redis because I'm just running on my local bus, my local machine here. So I'm going to come up to my app start.  And you'll note that I already have an app start method set up here ready to go. I just got this commented out.  So I've already installed a package called SignalR.Redis. So I just go to newget, install SignalR.Redis, which is going to pull in the bits that I need to use Redis and SignalR into my project.  And then it's going to add an extension method hanging off our I dependency resolver type that says useRedis.  And so all I have to do is pass in the address to the Redis server, the port, the password if there is one, and the event key I want to use to sort of segregate my messages for this app.  And that's it. And so if I build that, I now have to go off and obviously start Redis because my Redis server isn't running. So let's do that.  So this is PowerShell. I've literally gone to GitHub. I've cloned the Redis for Windows repository from GitHub and I built it using Visual Studio.  OK, it's C++. I just upgraded it from 2010 to 2012. And then I built it. And then I went to the debug folder and I'm running start process Redis.server.  So now Redis is running on my box. It's running on port 6379, which is good because that's what I configured it for, 6379. So that's good.  And then what I'm going to do is I have another command over here, which is going to kick off, where is it? This one.  I'm going to start my web farm. So it's not good doing scale out unless I have more than one web server.  So here I have two web servers. I've got IS Express on one side listening on port 8090 and then IS Express on another side listening on port 8091.  So let's kind of reorganize all these windows so this makes sense. So here we go. This is sort of a visual idea here.  We have one server on the left, one server on the right. Redis in the middle. OK, that's kind of cool.  So let's go ahead and connect some clients to this. So let's get my browser running. Let's get one browser connected to...  Let's see if I can do the resize shuffle here. Get one browser connected to a local host.  I want this to go to 8090 slash move shape.  So that you can see over here that IS spat out some stuff saying that things are happening.  So let's open another browser and move that one over here. And we'll connect that one to the other web server.  So you can imagine that I was in front of... I have a load balancer, right? And I'm actually just going to the same address.  And now when I drag, you can see that it's working. So a little bit lagged this time.  And it looks like I killed something. Demo fail.  Oh, there we go. It's just lagging. My machine is getting a little bit wacky.  You can see it did catch up. So even though it lagged, it did actually eventually catch up. All the messages got through.  So now that it's warmed up, it's actually working quite well.  So I now have two completely different web servers. So my application is running twice in two separate processes.  So there's nothing shared between these processes. And all the cross-process communication is happening through Redis, which is kind of cool.  Now, the one thing that isn't working, as you can see, is my connection count is wrong.  So can anyone tell me why my connection count is wrong?  I didn't saw that in Redis. Remember, it was just in a static dictionary.  So I've got a connection count of one in each server, which is correct for each server.  But obviously, if I was writing this app to be scale-out-friendly, I'd have to put that sort of information in some type of back-end,  either in a Redis store or a C-consever or something like that.  But that shows you just how easy it is to get scale-out working with SignalR using something like Redis.  Okay, so that's kind of cool. So that's one of the questions answered that people always ask, which is, how do I do scale-out with SignalR?  Well, you can.  The other question is usually around load and scale. How many connections can you support?  Well, I can tell you that, well, and we take this very, very seriously,  where we obviously want SignalR to be as performant as it possibly can be and support as many connections as it can.  With the current build on my machine at home, which is a Core i7-920, which is like a first-generation Core i7,  it's about three years old, so it's not a new machine by any stretch, but it's quad-core, hyper-threaded,  so it's a decent machine, but you could build one today for four or 500 bucks.  I can, with 5,000 clients broadcasting at 10 or 20 messages a second, get about 30,000 cents per second in that infrastructure.  So that's pretty good.  And a three-year-old machine getting about 30,000 cents per second for 5,000 clients.  Our bottleneck at the moment isn't CPU. In fact, the CPU doesn't max out during that test.  Our bottleneck is contention. We have a fundamental flaw in our Core architecture.  In 0.6, we're going to be re-implementing the Core of SignalR, excuse me,  to change how we sort of do our Core level PubSub infrastructure,  and we expect that number to drastically improve.  So we've got some very smart people on the ASP.net team, much smarter than me,  building custom data structures for doing message management at the moment.  So as I said, we have an in-memory message store, and at the moment we have some issues with garbage collection  because messages live for a while before they go away.  So while it works very, very well, and when you get under really, really heavy load,  like crazy heavy load with thousands of messages a second, you can certainly run into issues.  We have new message stores, infrastructures, which can do millions and millions and millions of messages a second  without breaking a sweat.  So over the next four to eight weeks, we're going to integrate that into the Core of SignalR,  and in 0.6, you should see the benefits of that.  And as I said, we'd certainly expect the throughput numbers to at least double, and if not triple.  So I'm certainly shooting for hopefully six-digit sort of messages per second throughput on my setup at home.  But that's all good. That's just talk.  Let's get a low test up and running here right now so you can sort of see how this works  and what tools we use to do our low testing.  So we have a performance harness for SignalR that we wrote called Flywheel.  We have these crazy names. I don't know how it started.  I think it started when David wrote a load generation tool called Crank.  And so I thought, great, Crank's connect to Flywheel.  So I'll create a harness called Flywheel.  And then within Flywheel, we'll have a class called Shaft, because Crank connects to the Shaft, which is on the...  Anyway, so we have these silly names.  We're running out of engine parts to call stuff, so it's not going to scale very well.  So we have this thing called Flywheel.  And if I run that up, what you'll see is it's a dashboard, essentially,  that spits out real-time information about what's happening on the server,  like how many messages are being sent through the message bus at the moment,  and graphs sort of the number of sends and the average sends per second.  So that's kind of cool.  And then from here, I can control how many broadcasts I want to do.  So obviously, there's no one connected to this at the moment, because it's just me.  I haven't created any client load yet.  So setting broadcast rate of 5 per second isn't really going to do an awful lot.  But we'll see how we do that in just a moment.  So I can set the broadcast size, I can set the broadcast rate,  and I can say what I want to do when the Flywheel receives messages.  So we also have in Flywheel something called Mini Crank.  Let's try that again. Mini Crank.  So Mini Crank is a page that connects to Flywheel, connects to Shaft,  and then says, I can say go ahead and send a message every 100 milliseconds.  So I'm now sending a message 10 times a second.  And so what we should see now, if I say, well, on receive, I'm going to echo,  we should see our send per second rate go up.  You can see it did, because it's echoing back messages as it receives them.  So that's kind of fun, but it's only one client, so that's really not that interesting.  Mini Crank is really not very useful for doing load,  it's just useful for testing that the harness works.  What we need to generate load is a real load test generator.  And so it's likely enough the IAS team builds one of those, it's called WCAT.  Anyone used WCAT before? Okay, like three hands, let me quickly show you WCAT.  So WCAT stands for the Web Capacity Analysis Tool.  Great name. Let's make the X64.  Make sure that most people are measuring and running 64-bit machines now.  So when you search, make sure you search for X64,  because the first page results otherwise won't show the 64-bit download.  It's kind of strange.  So you want to download WCAT 6.3 and install it.  It'll just run on any Windows box.  It's a native XE and some scripts that you can use to generate load, HTTP load.  Now, so while this isn't a signal or client,  I can make it do enough to make it generate load like a signal or client,  or at least listen to signal or broadcast, which is all I really care for doing load testing.  And so let's go back here and let's look at my WCAT setup.  So this is all available as well.  So we have a repository up on SignalR.  So I didn't actually tell you where it was.  Up on SignalR on GitHub.  So here's github.com.  So I go back up to SignalR.  That was way too many SignalRs.  There is a, here's Flywheel, which I just showed you, and here's Crank.  And in Crank, we have a folder called WCAT,  which contains all the settings files, which I'm about to show you,  that you can use to generate load against SignalR using WCAT.  So here's my WCAT folder.  If I look in settings,  most of this stuff is just copied from the WCAT samples and then tweaked.  So I'm going to emulate 1,000 clients.  So I'm going to have one physical client and then 1,000 virtual clients.  So 1X year is going to be 1,000 people.  So WCAT has the ability to have a controlling WCAT server  and then multiple WCAT nodes.  And then each WCAT node will be a client.  So you can make that client 10 if you have 10 client machines.  And then you can say each one of those client machines  is going to emulate 1,000 virtual clients.  And then that one WCAT server will control all the client machines.  It's actually a really, really cool little tool.  But I'm just doing this all in one box for the sake of a demo.  So then I have a scenario file.  So I have this shaft scenario file because I'm going to connect to shaft.  And you can come down here and you can see that I'm going to connect to port 29573.  And this is the URL I'm going to connect to to make it look like a signal receiving connection.  So here's that connect phrase that we saw before when we looked at the network stack in Chrome.  And I'm going to use the forever frame transport because it doesn't matter.  I mean WCAT doesn't support WebSockets.  So I just have to use either service end event or forever frame.  So I use forever frame.  And then I'm setting the connection ID to whatever the current virtual client index is.  So vClient index is just a function provided by WCAT to get the current number of this virtual client.  Okay. So I have a batch file that sort of runs all this together.  So it runs the WCAT script with all the parameters that you need to make this thing run.  WCAT isn't a user friendly tool.  Let me just tell you that.  It's quite finicky to get running.  So it is well documented.  It does have a fairly large word document, but it is a learning curve.  So it's nice to be able just to get some scripts that work and then run it.  All right. So we have, let's find my WCAT.  There it is.  So we have flywheel running.  Let's see if it's still there.  There it is.  Okay. Let me pull that out.  Let me pull that down there.  Let's minimize that one.  Let's put that up there.  Let's come here.  So currently I have no clients connected.  You can see over here, no clients connected.  Clients is zero.  So let's start up WCAT.  Okay.  So WCAT is starting.  So we can now see that connected clients are coming in.  You see it's starting one virtual client every so many microseconds.  So I'm going to go up to a thousand clients.  So now it's sort of in its listening mode.  It's still starting up clients.  I'm going to get to a thousand.  Okay.  So now I'm going to start broadcasting.  So let's broadcast at five messages a second.  And what we should see is that I get about 5,000 cents per second because I have a  thousand clients.  I'm doing five broadcasts a second.  So that's 5,000 cents per second going through the system.  And indeed, so far, this machine is able to cope with that, without any problem.  We don't start running into that contention limit that I talked about in our core of  our architecture at the moment until you get to about 30,000 cents per second.  And this machine wouldn't be able to handle 30,000 cents per second anyway.  So you can see the CPU use, you know, is pretty high.  It's actually, funnily enough, a lot of it is drawing this graph.  If I look at the process, that's crazy, I know.  If you look at the CPU, look, Chrome is using 38% of my CPU.  So test, just a little lesson.  Don't run everything on the same box when doing low testing.  Don't run your dashboard on the same box as your server because drawing pretty graphs  with Canvas on SVG takes a lot of CPU cycles on the browser.  So you can see my web server, IAS, is actually only doing like 40%, 30 to 40%.  And so it's actually the browser that's taking up most of the rest of the CPU at this time.  So that's going to run for, I think, 90 seconds, is the test duration.  So we'll just let that run because I want to show that what's going to happen when the test finishes as well.  So you can see there's been no errors.  WCat will keep spinning out all the stats every 10 seconds from the last 10 seconds.  Now, because these connections never end, nothing comes out.  Usually WCat just makes requests, and then as soon as the request comes back,  it makes another request again. It's designed to generate load, right?  But I'm using it to simulate persistent connections.  So it just makes the connections, and then because I never end them, they just stay open.  And WCat just sits there going, OK, connection's open.  I'll just keep it open and just keep spinning out empty stats.  WCat's fantastic because it has virtually no memory overhead.  It's a native client.  It happily receives everything I send to it from the server and then just throws it away again.  It just uses no memory. It's fantastic.  Incidentally, I did manage.  I'm using a 32-byte payload here.  On my infrastructure at home, I have a dedicated gigabit switch,  and then I have a separate machine that I use to emulate the clients.  And so when I ran that machine with 1,000 clients against my server  through my dedicated gigabit switch with a 4K message size,  I was able to saturate the gigabit nick on the client machine.  So that's always a really, really good indication of your low test.  If you can saturate the nick, that's good.  That's really, really good.  It means that your bottleneck isn't CPU or memory or anything else.  So the test is finished now.  You can see nothing is sending anymore. No one is connected.  So if I scroll over, we should see I still have people who are connected.  So remember I said there's the idea of a graceful disconnect and a non-graceful disconnect?  So WCat finished, but it doesn't know to send that packet  that signaler understands that the connection went away.  So the connections were still alive on the server  until such time that our background process came around  and realized that they were dead.  And you can see that that happened.  So at this point here, our background process realized those connections were no longer there  and would fire the disconnect event for all of those connections.  So even though WCat weren't gracefully disconnect using a signaler, graceful disconnect,  we came ahead and cleaned up those processes without any problem.  So interesting point in terms of scale and RAM.  I've talked about CPU and I've talked about connection.  I've really talked about RAM.  Where's my IS express process?  Do it that way.  Okay, so that's probably the one.  I'm assuming the one that has all the memory.  100 meg.  ASP.net has out of the gate about 40 to 50 kilobytes  of managed heap size overhead per connection.  I'm not going to lie to you.  It's fairly heavy.  So once we fix the sort of contention problem that we have in 0.5,  which we'll fix in 0.6,  your major limiting factor for scale is going to be memory.  So we have actually driven signal up on a single box to 100,000 concurrent connections.  And I think it used 40 gigabytes of virtual memory or something crazy like that.  Because of this sort of limit in ASP.net.  Now we are working on in 4.5, things have improved.  And if you're using web sockets on 4.5 on Windows 8,  that overhead is drastically decreased to like single digit kilobyte overhead per connection.  And so it does get a lot better.  But you can host signaler outside of ASP.net.  Signaler is not an ASP.net library.  It's a.net library.  And we are host agnostic.  The default setup when you new get in signaler is host on ASP.net.  But you can host on whatever server you like.  And indeed in 0.6, we're going to standardize on OWN as our hosting layer intrinsic.  So if you want to host on a different server, like self-host using hdb sys,  or a socket server like flywheel or kayak, which are open source C-sharp web servers,  you can absolutely do that because we'll support OWN and those things support OWN.  So you'll just be able to host signaler on top of whatever it is that you want.  And there are people in the community who have already written custom signaler servers  in order to do their own hosting from within their own XE.  Now again, I think 99.99% of people who use signaler are going to use it in ASP.net  and they'll never have to worry about that.  But if you're going to be doing really, really high concurrency,  lots of clients per machine sort of deployments,  then a custom server might make sense if you're not going to be using WebSockets  just because of the memory benefits that you'll get.  You'll be able to support more connections per server, which is kind of cool.  Okay, so we're nearly out of time.  I've pretty much shown everything I wanted to show.  So we have two minutes left for questions.  Anyone have any questions? Yes?  Mobile clients.  What's that? Sorry?  Mobile clients.  Mobile clients. The question is mobile clients.  Do we support them? Yes, we do.  So if I go up to GitHub and we look at the repository,  you'll note that we have a bunch of clients by default.  So there is clients for Windows Phone 7, clients for Silverlight.  The JavaScript client is just in the signaler library.  There's a client for Windows 8, Metro apps.  And there's a client for.NET itself.  So if you're just using like a WPF app like I did that's an audit client.  The community has contributed an iOS client.  There's an iOS client that someone else maintains.  There's a MonoTouch client that someone has built.  There's a Java client I believe someone has built.  Someone built a Node client.  I have no idea why, because Socket.io is great.  Use Socket.io if you're on Node, but they did.  And I believe there's a MonoDroid client as well available.  Now, our current thoughts for version one of SignalR  is we would like to have all those clients sort of built by the team and supported.  Because we think SignalR is much more attractive the more clients it has.  So look to see, ask, pull those clients in or build new versions of those clients  for version one whenever they get down.  Any other questions?  Yes?  So the question was what about T4 templating instead of generating the script dynamically?  So one of the problems with generating the hub proxy at runtime  is you don't get IntelliSense on the hub in Visual Studio.  It's kind of nice in JavaScript if you can get that.  We do have some prototypes of that and it is on our backlog to support design time  slash compile time generation of that file so that you'll get IntelliSense.  I do believe actually something has already checked in that does that.  I'm not sure that it uses T4.  I think at the moment it uses an XE so that you can just run that from inside your build file  so that it'll just build the JavaScript file and jump it into your project.  And you'll just reference that JavaScript file rather than that magic route that I showed you before.  So yes, we are working on that. Yes?  I've seen on iCat for instance you get the constant loader.  Yeah.  Is that something you know?  So the question is on some clients with some of the transports you get the little loader spinny  to stays there forever.  It's a registered issue.  We're looking at it.  The current fix that we have that we're testing out is just to delay the creation of the transport  with a set timeout.  So rather than doing it immediately just say set timeout 250 milliseconds and then create it  and that seems to fool the browser enough.  It seems crazy that a browser would support service end events and then show the spinny  while the thing is open but they do.  Some of them, iOS in particular.  So we are going to fix it.  Yes?  Yep.  Right.  So I think, let me rephrase, the question was about graceful disconnect and IE and IAS  and about what combination is required to support the graceful disconnect?  Right.  So IAS has this ability to asynchronously notify your code when a client disconnects, which  is nice.  Now that's not graceful disconnect.  Graceful disconnect in a signal our terms is when the signal our client tells the server  I'm about to stop the connection.  So any browser that will run our code on window unload and let that Ajax request go through  will support graceful disconnect because then we'll just receive an Ajax request on the  server that is a disconnect command and then we'll disconnect the client in our server.  If that doesn't get received and there's a couple different ways that we can detect the  client is disconnected.  IAS 7 and above gives us this is the, IAS 6 and above gets us this is client disconnected  property on the response object that we can essentially poll.  So every 20 seconds we check the connection and say is client disconnected false?  Oh it is.  So the client is now gone.  Let's see if it's over the disconnect threshold and then we'll disconnect them.  In ASP.net 4.5 we've added if you went and saw my talk this morning there is a new asynchronous  notification you can subscribe to to get told when the client goes away because IAS 7.5  or above supports this and so if you're using ASP.net 4.5 on IAS 7.5 you'll be able to subscribe  to a cancellation token on the request object that will fire when the client shuts down or  closes the connection.  Assuming that that gets to you know because underlying the TCP level connection there will  be a message sent up to the server and IAS will bubble that up asynchronously to your  code.  So we do our best whether it's graceful or disgraceful, no that's not right, graceful  or not disconnect to try and notify your code that a client has gone and do it in the most  timely manner that we can and try and ensure that we only do it once.  That was a big problem in disconnecting web farms that we didn't fix until 0.5 is how do  you handle the fact where I connect to server 1 and then I reconnect to server 2 now server  1 is going to fire a disconnect event.  So we had to handle we have to have cross node collaborations such that when you connect  to server 2 server 2 can tell all the other servers hey I now own connection 1, 2, 3,  4 everyone else just forget about it don't fire the disconnect event.  So that's what we added in 0.5 to make disconnect work in web farms properly.  So I'm out of time but I'm happy to keep answering questions while people are still  here because it's 15 minutes until the next guy so.  Oh actually it's only the party now so I'm just keeping you from drinking so if you want  to know more I can do that but thanks for coming along and try it out.
Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_0_1823.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_1824_2951.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_2952_3167.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_3168_4271.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_4272_4343.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_4344_4787.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_4788_5519.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_5520_6467.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_6468_7343.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_7344_8375.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_8376_8711.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_8712_9191.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_9192_10271.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_10272_12755.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_12756_12911.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_12912_12983.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_12984_13979.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_13980_14027.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_14028_14075.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_14076_14759.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_14760_14867.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_14868_14987.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_14988_22967.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_22968_24203.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_24204_25211.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_25212_25475.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_25476_25607.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_25608_25811.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_25812_25955.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_25956_26111.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_26112_26291.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_26292_26843.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_26844_27215.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_27216_27875.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_27876_28283.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_28284_28379.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_28380_28427.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_28428_28715.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_28716_30563.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_30564_32291.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_32292_33047.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_33048_36119.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_36120_36239.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_36240_36527.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_36528_37859.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_37860_39179.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_39180_39551.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_39552_40331.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_40332_40883.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_40884_41111.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_41112_42707.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_42708_43115.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_43116_43967.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_43968_44051.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_44052_45371.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_45372_46067.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_46068_49199.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_49200_55355.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_55356_56219.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_56220_56639.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_56640_62783.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_62784_62867.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_62868_63419.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_63420_63467.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_63468_63995.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_63996_66479.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_66480_70043.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_70044_70547.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_70548_70679.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_70680_70907.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_70908_72707.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_72708_72755.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_72756_73943.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_73944_73991.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_73992_74435.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_74436_74591.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_74592_74807.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_74808_74963.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_74964_75083.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_75084_76703.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_76704_76967.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_76968_77087.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_77088_77843.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_77844_77903.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_77904_79583.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_79584_80687.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_80688_82847.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_82848_83747.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_83748_85463.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_85464_87983.png Damian_Edwards_-_SignalR_Awesome_in_Real-Time_with_ASP_87984_96684.png
I am losing my voice, but I will do my best to get through this next hour for you. I'm a program manager on the ASP.net team at Microsoft, but today I'm going to be talking about a project that me and another guy on the ASP.net team, David Fowler, started in our own time last year called Signalar. Signalar is a persistent connection abstraction for.NET. So how many people have heard of Socket.io on Node? Okay, a few people, almost everybody, which is good. So Signalar is kind of like Socket.io for.NET, but we also have elements of Now.js, which is another library for Node that builds on top of Socket.io in Signalar as well. But again, it's all for.NET. And so if you're using Node already for real-time stuff, that's fantastic. Socket.io is a fantastic library. I'm not here to tell you that we're better than Node or anything. I'll leave that to tomorrow in the cage match with Rob Connery. But if you're a.NET developer and you want to do real-time development, then Signalar, I would hope, is something that you want to have a look at. So without further ado, I don't have any slides. I really don't like using slides these days because most of the talks I do are full of code. So let's just write some code and we'll learn how this thing works. So I'm going to start a new empty web application. And then I'm going to sort of new get in the world. So I'm going to say manage new get packages. And then from a local feed, I'm going to install Signalar.sample. So we have this working sample package for Signalar, if my machine is there. So here we go. That you can pull into your project. It pulls in all the required dependencies, obviously, that are needed to get Signalar itself working. And it pulls in some working code. So we can see here we have the beginnings of a stock ticker. Now, this is not a real stock ticker that connects to some service in the cloud. It's just some background thread that gets kicked off and fakes out of stock market. But it's a good indication. It's a good sort of learning tool to see how something might work. So let me go ahead and run that up. We can see that I've got that running over in one browser. I'm going to launch another instance and put that over here because real-time demos are always that much more impressive than we have two browsers. So hit me open market and you'll see that the changes are synchronized on both sides because we have two browsers connected to the same Signalar endpoint on the server and receiving information from the server and updating the UI as appropriate. So obviously in this case the client is JavaScript. We do support multiple clients and we'll talk about that later on. And the server, of course, is.NET. And I can go and hit close market here and you see it synchronizes on both sides. So while the majority of this is the server pushing to the client, when I click a button, obviously the client is pushing a message to the server and then that's resulting in the UI changing in both of the connected clients. So that's great, but let's go ahead and build something from scratch. That's perhaps a little bit simpler so that we can get an idea of what this looks like. So I'm going to add a new folder and we'll call it move shape. And inside this folder I'm going to add a class and I'm going to build my server-side logic for my move shape application. So I'm going to call this the move shape hub. So we have two levels of API server-side in Signalar. We have a low-level connection API, which is very similar to Socket.io. It is literally mimics a socket. So you open a connection, then you can send messages on it and you receive messages on it. You get an event when someone connects and you get an event when someone disconnects. And that's about it. So if all you care about is sort of the raw socket level stuff, you can program at that API and good luck to you. But most people like to use what we call hubs. We have this higher-level API called hubs, which lets me do reverse sort of procedure invocation from the server to the client. And vice versa, obviously the client can call the server. So I'm going to go ahead and create a hub. I'm going to derive from hub. I'm going to decorate this with an attribute that lets me change the hub name on the client. So I'm going to call it move shape on the client, because I like this word hub appearing there. I'm going to say public void, move shape. I'm going to take in an x and a y from my client. And whenever that happens, I'm going to go and tell the world that someone has moved a shape. And the way I do that is by accessing this client's member. And if I sort of zoom in here and have a look at clients, what you'll note is clients is dynamic. So clients has a property on hub, and clients represents all the people who are currently connected to this hub via signaler. And I can now go ahead and invoke a method in my client from my server-side code. Now that client might be JavaScript, it might be a.NET client, it might be iOS, it might be Monotouch. But in this case, it's going to be JavaScript. So this is dynamic, because obviously this isn't.NET code that's going to be running here. This is going to be something that's sent over the wire and invoked on the client. So I'm going to say shape moved, and I'm going to pass in the current connection ID. So that's going to be context.connectionID, so that they know who did it. And then the x and the y that was passed through. So that's my server code done. Let's add some client-side code. So I'm going to have JavaScript file, move shape. Now I need to pull in another library here, so I'm going to go back to newget, go to my Dropbox feed. I'm going to look for jQueryUI, install that. Wait a moment, pause for dramatic effect, there we go. I'm going to drag in jQuery, drag in jQueryUI, and I'm going to start writing some signaler client code. Actually I may as well drag in signaler in here as well. This is just for IntelliSense reasons. So I'm going to go ahead and get my hub. So that's dollar.connection.moveShape. We'll talk a little bit more about how that turned up in just a moment. And I'm going to have some type of UI on the screen that people can move around. So let's just say it's going to be an element called shape. So let's go ahead and find that. Okay, so now that I have my client-side hub, moveShape, I have to add that method that I want to be invoked. So if we go back here, we saw that I'm going to invoke a method called shapeMove. So let's add that method. I'm going to use jQuery's awesome extend method to do that. So for those of you who haven't used extend before, all it does is say take the object here and add anything that's on the second object to the first object. So I'm going to add a method called shapeMove. And that method has to take a number of parameters from the server. So connection ID, x and y. If we go back to here, you can see I'm passing connection ID, x and y. So I have a matching method signature on the client. And then I'm going to check to see that this wasn't invoked by myself. Because I'm going to be listening to all messages. And when I broadcast something to, when I send something to the server, I'm going to get that same message back again. So I'm just going to do a little check here to make sure that this isn't a message that originated from me. So I'm going to say if dollar.connection.hub.id is not equal to connection ID. So it's not from me that I want to go ahead and move the shape on the screen to this new position. So I'm going to say dollar.shapescss. Left is equal to x and y is equal to top. Oops, get my bracing right. Okay, so now that I have my client side method, I need to go ahead and wire up the client side logic and then call the server whenever I move this shape on the screen. It should be top equals y, I think, very much. And I've already got my first correction from the crowd. Fantastic, price for you, sir. Left, x. So now I have to go ahead and wire up the client. So first I need to go ahead and start the connection. So I'm going to say dollar.connection.hub.start. And then when that's done, I'm going to pass in a callback here that will get invoked once my connection has actually started. I want to go ahead and enable the sort of dragging behavior so this can get moved around. So I'm going to say shape.dragable, which is that jQuery UI function that I brought in. And I say when that gets dragged, go ahead and invoke this function. And when that's dragged, I want to call the server and tell the server, hey, what's the position of the shape? So I'm going to say hub.moveShape. So again, moveShape is this method here on the server. So this is my hub. I'm going to call hub.moveShape. And I have to pass in x and y. So that's just this.offsetLeft, this.offsetTop. Like so. Okay, so that's my client-side code done. Let's add a page to actually show it on. Let's add all these JavaScript packages that I need. So I need that one, I need that one, I need that one. Let's drag those into here. And I need to add an extra magic script reference that we'll look at in just a moment. That's going to pull down some dynamically generated JavaScript to make this sort of signal magic happen. So signalr slash hobs. I'm going to add my div with an ID of shape. And so that you can actually see my shape, let's add a style block. And we'll say shape. Width is 100 pixels. Height is 100 pixels. And background color is some new... Let's have a look. This time blue over here looks pretty good. Okay, so that's my app. Let's run that up, see if I made any mistakes. Okay, so it's showing there, that's a good start. Let's open another browser instance, put that over here. Paste that in there. And if I pick this up and move it, you can see that it moves in both sides. So really, really easy to get going with signalr doing these type of broadcast scenarios. So let's tease apart this demo a little bit now and try and get an understanding of why this even works and what's going on under the covers. Okay, so let's have a look. Let's bring up the network tab here and we'll hit F5. We'll see a few things that happen when zooming down here. So as Remember I said, signalr is an abstraction. It's an abstraction over various ways that we can in HTTP mimic or actually achieve a full persistent connection between the client and the server. So how many people have heard of WebSockets? Everybody. Okay, good. WebSockets is kind of synonymous with this new move to the real-time web. The problem with WebSockets is they don't work. They might work if you have a browser that supports them. If you're a.NET developer, they'll work in ASP.NET if you have Windows 8 on your server and using.NET 4.5. They'll work if your hosting provider supports WebSockets through their reverse proxy and load balancing infrastructure. And if your client is behind a firewall or a proxy that also won't trample on WebSockets. If all of those things are true, then yes, you'll get a WebSocket connection from your client to your server. Now, we know all those things aren't going to be true for quite some time yet for the vast majority of people. And so libraries like SignalR and Socket.io exist to help us bridge that gap. What do we use when WebSockets isn't available? They also give us a much nicer, higher-level API. Who's actually programmed with WebSockets? Okay, only a couple of people. It's hard. WebSockets is sockets. So you don't get any of the niceties I just showed you. It's open a socket, send a message. So you have to do all your own dispatching. You have to do your own invocation logic. It's basically just sending strings or binary data back and forth. If you've ever done socket programming before with raw sockets, it's basically similar. And the server-side programming, and that's just the client side, the server-side programming is even harder. There's a specific way you have to do WebSocket framing. You have to ensure that messages are sent in order. You have to ensure that you're only ever sending one message at a time on a connection. So there's all these types of buffering and synchronization code that you have to write if you're not using a framework that does that for you. So it's nice to have a high-level framework so that I don't have to worry about that type of stuff. So if I don't have WebSockets, what can I use? So we fall back to a number of different things. So if we come down to this request down here, you can see that there's a request to an endpoint called Negotiate. So the first thing that SignalR will do is make a standard Ajax call to the server saying, hey, I need to negotiate a transport. I need to figure out what can I use for me, client, to talk to you, server, in somewhat of a real-time fashion. Now, we'll start out with WebSockets, and then we fall back from there. Now, we'll only attempt to use WebSockets if the server says it can support WebSockets. If you're running on top of ASP.NET, that means you're on ASP.NET 4.5 on Windows 8 with IIS Express 8 or IIS Express 8. Now, most people aren't there yet, so most of the time you're not going to be using WebSockets just yet. You'll then fall down to something called Server-Send Events or Event Source. Server-Send Events is a technique or actually an API that you can use in the browser in all browsers except IE. That lets you have a persistent connection from the server to the client such that the server can push information down to the client. So if WebSockets isn't available, we'll try and use Event Source. That will generally work in all browsers except for IE. So we skipped Event Source for IE, and then we go down to the next level, which is Forever Frame. Anyone ever tried using Forever Frame? Ever heard of that technique? A couple of hands go up. So Forever Frame is the idea of having an iframe embedded in your document that makes a request, loads of document from the server, and all that document in the iframe does is spit out script tags, and it never finishes. So it's just an ever-growing document full of script tags, and the great thing about browsers is that they'll execute script tags as they get them, even before the page is finished loading. So you can have a hidden iframe with a document in it that gets script tags that contain the messages that you want to be sent to the client, and it'll happily keep invoking them for you. So Forever Frame will be used generally in IE because it supports Forever Frame quite well. And then if none of those things are supported, which is unusual, but it can happen depending on the infrastructure between the client and the server, perhaps the router or something doesn't like a persistent HTTP connection, then we fall back to the lowest level, which is long polling. So the idea of long polling, when we all know what polling is, right, polling is, I call the server, have you got data? It replies no. So I say, okay, after some period of time, I call the server again. Do you have data now? No. So I wait a little bit longer, and they say, hey, have you got data now? Yes. Okay, so now I have data, and then I wait a little bit more, and then I poll. Long polling is the idea of saying, let me call the server and say, have you got data? And the server doesn't return until it does. And so that connection stays open until there is data available to sort of fill that request. And then once that request comes back, I process it on the client, and then I send immediately another request saying, hey, have you got any more data? And then that stays open until there is more data. So long polling is advantage over polling in that while there is no data flowing, you have an open connection, but you're not really using any resources other than those taken up by an open connection. You're not constantly hitting the server with a request that doesn't result in any data, which is kind of nice. It also has very low latency compared to polling because you're going to get the data as soon as the data is available, assuming you have a connection open. So we had a negotiate request, and after that we had a connect request. And if we look at the URL for this, zoom out a little bit, we can see that over here, we have signalize slash connect. So now that I've done my negotiation, I'm going to connect to the server with the connect verb. I'm going to say transport equals server-cent events. So the client and the server negotiated server-cent events because WebSockets wasn't available. And then server-cent events, as I said, is this one that Chrome, Firefox, Opera, Safari support. And then once that's open, what we'll see is that thing stays open. So we should see over here, here's that server-cent events message over there. You can see it's been over open for two minutes, been receiving for two minutes. And if I come over and open another browser now, let's do this one over here, so let's push this one back. And if I move this around, we'll see that that bar changes if it doesn't make a lot of me. Let's see if I can make this a little bit easier to see. It might be easier if I just refresh. There we go. So here's my connect down here. As I move this around, see how that gets longer because it's currently receiving information from the server so that load time for that request just keeps getting longer and longer and longer. And that request will just stay open while it's receiving data until either the timeout kicks in. So there's a default timeout of two minutes at which point it'll reconnect or something goes wrong, obviously. Okay, so that's sort of the intrinsics of negotiation, negotiated transport, and then get a connection as a result of that. So what else happened in that negotiate request? Because there's other interesting things that happen in here. We zoom into here and have a look at what was returned. So we get a JSON payload back from the server when we negotiate, which gives us a URL, and we get a connection ID. So that's interesting. We know that every connection that connects to Signaler gets a unique connection ID. Now, in this case, it's a GUID. You don't really have to worry about it. We'll have a look a little bit later on when you'd need to worry about mapping this connection to something useful. But this means that you can address people individually using Signaler because you have a connection ID through which you can identify them, which is kind of cool. You can also see that we sent back a flag saying whether we should try WebSockets. So on the server, we determined whether WebSockets was even going to be supported. And if it wasn't, we tell the client, don't even bother trying because it's not going to work. Okay. So that was a very, very simple demo. Let's move on to something a little bit more convoluted. We do support something, we do support more clients than just JavaScript. So let's open up a slightly more complete version of this application. Let me go ahead and find it. And let's open this one here. So this is the same demo that we just saw. It's move shape. It has move shape. It's basically the same thing that I just showed you. It's just a little bit more UI and a little bit more logic in the client. But other than that, it's the same. So if I run it up, you can see here it's pretty much the same as we had before. And now I'm telling you how many clients are currently connected as well. So I've got this number in the top right-hand corner. So how many people are currently connected? So what we also have here, though, is a different sort of client. I have a WPF client. So I'm going to come in here. I'm going to show up this move shape desktop. Come back and open this one. Let me pin this to the right. And now when I move this around, you'll see that I've got my WPF client also receiving this information from the right-hand side. And similarly, I can move from the left to the right. So the code for this looks pretty similar. Let's go back and have a look. So let's have a look at my... I'm not the greatest WPF programmer in the world, but I can sort of model my way through it. So it's just a canvas with a shape inside of it and a text block for the number of clients. And then the code behind for this canvas is... I have an async void method go because SignalR is async from top to bottom. In order to scale in ASP.NET, it needs to be asynchronous. If you're going to keep connections open for a long period of time, they have to be asynchronous because you don't want to be using a thread when that connection is doing nothing because you're just going to run out of threads and then your server won't be able to serve any more connections. And so SignalR is async top to bottom, both on the client and the server. And so you can see I go ahead and it looks kind of similar to the JavaScript code. I knew up a hub connection. I go ahead and create a proxy for that hub connection. Now in JavaScript, that was done for me automatically. I'll go back in a minute and show you how that happened. But when I imported that JavaScript slash SignalR slash hubs, that was a hub proxy being created for me. So I have to create it manually over here in.NET world. And then rather than doing method invocation, I'm handling method events. So I'm saying when the hub raises an event called shape moved, go ahead and invoke this delegate using these strongly typed parameters. So connection ID XY. And look very, very, again, very similar to what we had in JavaScript. Although now it looks like WPF. I check if it wasn't myself and then if it wasn't, I go ahead and invoke this delegate back on the UI thread to go ahead and move the shape on the canvas. And now that I'm also tracking connected clients, I get a message whenever that client count changes. So when I connected and I got two clients, I got a message and I go and invoke that as well. Then I go ahead and start the connection. And I await that because it's asynchronous. And then once that's finished, I go ahead and enable the draggable UI. Now this draggable is just my own sort of ghetto extension for WPF that makes something draggable on a canvas. So don't worry too much about that. I've just sort of emulated what jQuery UI does. So I've said it's draggable and then when anyone drags it, go ahead and invoke this lambda and tell the hub to invoke the move shape method and set the left and top based to what this is here. So kind of the same stuff. So there is an interesting thing that was different on the server though. Let's have a look at that. So move shape. So here's my hub, very similar to the one we had before. But I've got two interfaces that I'm implementing this time that I wasn't before. I connected and I disconnect. So signal as a connection abstraction gives you connect and disconnect semantics. And so you can get alerted whenever someone connects to your hub or your connection and alerted when they disconnect as well. And so for a hub, the way to do that is to implement these two interfaces. I connected and I disconnect. And then we will invoke your connect method whenever someone connects to the hub and we'll invoke your disconnect method whenever someone disconnects from the hub. Now we also have a reconnect intrinsic, which you can handle as well if you want to. And that can be useful to ensure that when clients reconnect, they are going to say that they're a member of a period of groups and you can check whether that's actually true. So I'll talk about that a little bit more in a minute. So the interesting thing here is that I'm showing how you can go ahead and track connections. So one of the questions we very often get when talking about SignalR is, how do I get a list of clients? And the answer is you don't, because there is no list of clients. SignalR at its core is built on a PubSub mechanism. In order to enable scale out, which we're going to look at a little bit later, we don't store state. So if we were able to give you a list of clients, it would be very difficult for us to scale that out in a web farm because obviously you can have a thousand clients connected to one server and a thousand clients connected to another. And if your code is running on the second server and says, give me a list of clients, how does it know what clients are connected to the first server? Unless you're sharing some sort of back end state. And so there is no list of clients. What you have is a list of signals, not even a list, just arbitrary keys, arbitrary signals that you can broadcast to at its very, very core. Every client gets its own signal, that's what that connection ID is. Every endpoint gets its own signal. So this move shape hub will have a signal called move shape hub. And whenever you send a message to move shape hub, we literally send a message through the message bar that says, broadcast to move shape hub this payload. And the payload for hubs will include what method it is that you want to invoke and the arguments that you want to pass to that method. And so it's up to you to track connections and who exists on what connection. So in this case, I just have a static concurrent dictionary, because this is asynchronous. I could have multiple threads operating on this hub at one time, so I have to have a concurrent dictionary of connections because it's static. And then whenever connect is called, I go ahead and just add a record to that concurrent dictionary keyed by the connection ID. And then I go ahead and broadcast out to all clients the current counter to that dictionary. So I'm just using this dictionary as a way to track how many people there currently are in my app. Now, obviously, this wouldn't scale out because it's a static in-memory dictionary on this class. But you can imagine in a proper application, this would be stored in a database or in some type of distributed cache so that you could actually do proper how many people are currently connected sort of intrinsics. So similarly on disconnect, I go ahead and try to remove that and I now update the counter appropriately. Now, what isn't shown here, which is interesting to note, is that the relationship from users to connections is one to many. So if you have the concept of authentication in your application, then obviously people will log in using some type of credential and then they have some type of username, so it might be Damian in my case. And then when I use SignalR, I'm logged into your app as Damian, and then I'm going to connect to your app with a connection and that connection has a connection ID. So I need to store somewhere the fact that Damian is currently on connection 1, 2, 3, 4. And so that should be persisted away in your database or persistent mechanism so that when someone says, hey, I want to broadcast a message to Damian, you can look up the connection ID that Damian is currently on and then send a message to that connection ID. Now, I did say it was one to many though. I mean, I can obviously open more than one browser, or I can open a browser and iOS app or a Windows phone app and connect to the same thing with the same user, but I'll have different SignalR connections. So the recommended practice is to ensure that you're storing one user to multiple connections. Now, for a good example of how this works, we have sort of our smoke test app up in the cloud, this chat app called Jabba. So Jabba is sort of an IRC clone written on top of SignalR. It's hosted up on Windows Azure, but that's kind of incidental. And it's the sources available in GitHub, so you can go and see what it's like to build an ASP.NET application of this nature that's real-time using SignalR. And this uses SQL Server, it's underlying persistence mechanism, so you can see how all the user names are persisted, how the user names are mapped to individual connections, how we handle connect and disconnect. You can see as I'm talking here, people are typing and we're getting little speech bubbles that come up when they're typing, so it's more than just messages flowing back and forth. We actually have things like status indications as well. Jabba has some really interesting stuff as well. It has content providers, so if I keep scrolling up here, I should be able to find an example where someone has posted a JPEG, like so, and then we have sort of built-in content providers that will then go down and pull down that JPEG and throw it in the room for you, which is kind of cool. So it's a really nice application for learning the type of things you can do with SignalR and what you can do with real-time. So, well worth pointing out. It does get a little bit wacky in general chat sometimes, so I tend to stick into the more focused rooms, so to say. Okay, so let's go back to the JavaScript client for a moment because I talked about this creation of the proxy that I didn't really elaborate on. So if we go back to my index, we can see this SignalR slash hubs request that I put in here as a JavaScript file. Let's have a look at what that actually is. So let's bring up my network stack again. It's at F5. Let's find that one in here. So here it is, SignalR slash hubs. So we can see what we pulled down was a JavaScript file, but this JavaScript file was dynamically generated on the server. And if we scroll down, there's a whole bunch of wire-up stuff which is interesting, but not what I really care about. What we'll see down here is this part. This call to $.extendSignalR with myHubs. And so you can see MoveShape was my class, my C-sharp class on the server got turned into this JavaScript object that has a method that I can invoke that goes ahead and calls this server call function to actually make the call on the server. So it kind of appears like magic, but really all that we're doing is generating some JavaScript. It's really generating a proxy, just like you would have done back in the old days when you added an Asmx reference or WCF reference using Add Service Reference in Visual Studio. And then it would generate you a JavaScript proxy if you added it to the script manager in webforms. It's kind of similar except we do it at runtime. And we also allow the server to call back into the client. And so we get this really, really nice sort of back-and-forward remote procedure call paradigm that we can do between the client and the server, which is kind of cool. Okay, so that's how that works. Let's have a look at some other interesting things. So WebSockets. So I said that WebSockets wasn't running in this demo and it isn't. So the version of SignalR that's available up in Nuget right now is 0.5.0. The next version, 0.5.1, will come with WebSockets support in the box. So I actually have the source application open right here so we can have a look at what WebSockets support looks like just to prove to you that it does work. So it does require Windows 8 on the server, so I'm running Windows 8 Release Preview here. I'm running Visual Studio 2012. Oops, that's a known problem. Let's go back and close that and try that again. Rebuild. I'm running Visual Studio 2012 RC, which comes with IS Express 8. And so because I'm running IS Express 8 on top of Windows 8, I get WebSockets. So if I F12 in here and I hit F5, what we'll see down here is a different sort of request. So I'm in a browser that supports WebSockets. I'm in Chrome. And we can see the negotiate happened. If we look at the negotiate this time, we can see that Try WebSockets is true. So we're going to get an attempt for WebSockets, which is good. And I get this, Connect Raw. We can see that the URL there says transport equals WebSockets. And then you can see the status from the server was 101 switching protocols. So this is how WebSockets works. WebSockets is an upgrade request. A standard request is made to the server. It's a get request. You can see that here, get. And then it says in there, there is a header that says, hey, I want to upgrade this request to a WebSocket request. And then if the server replies with the 101, that means, yes, party on, we now have a WebSocket. We can now do persistent connection. And so we won't see any other, if I go ahead and start broadcasting stuff now, there are no other requests happening because I have a WebSocket. This thing is just there happening underneath the covers now. Now, I do have Chrome Canary installed here. And in theory, ooh, okay, see what that does. Chrome Canary is supposed to give me WebSocket inspection capabilities. Let's have a look at this works. I've actually tried this. I'm going off script here. So let's go network. Let's F5. Here it is. There's my WebSocket. And if I go to here and I go to WebSocket, look at that. There's my WebSocket frame. Sweet. So if I broadcast stuff and I come back to here, there's the WebSocket frame. So you can actually see the messages flowing over the WebSocket. And it even shows you the direction. So this is saying coming from the server, that right to left. And this is the JSON payload that Signaler was sending back from the server to the client. So you may have noticed that Signaler has its own protocol. You connect to a Signaler server with a Signaler client. It's much like Socket.io. This is our JSON protocol. So we wrap whatever message that you send, which is we serialize whatever you send as JSON, you can just send random.net objects. We'll serialize them with JSON. And then we wrap that with sort of a message framing protocol, which itself is JSON as well. And so that's what you'll see flowing over the wire. So that's kind of cool. We've got WebSockets running there, which is nice. So we have some other samples in our sort of sample project that's up in source. That's my daughter, Elizabeth. That was raw connection that I just showed you there. We have an example of just streaming. So in this case, all we have is there's a background thread on the server that is just pumping messages to the client. So rather than any type of interactivity, I just have a dumb client that's just listening passively to messages. A bit similar to the stock ticker sample I showed you originally. We have this mouse tracking one, which is kind of cool. So every person who connects gets a cursor and with a little number on it. And you can see that update in real time, which is kind of nice. We had that up to some ridiculous number and it does get a little bit strange after you've got dozens and dozens or even hundreds of people in there. We have this one called ShapeShare, which is sort of a more advanced version of the MoveShape demo I showed you. So I can put this one, I can actually add a username in here. So I have left, right, and then I can add a rectangle and I can move that round and I can add a picture. And I can move that round and I can sort of resize that. And you can see that it says change by right. And if I move it, it says change by right over here. It says change by left. So the source for that one is quite interesting because it shows mapping usernames to connection IDs. So that one is worth checking out when you go and get latest from GitHub. And then we have a drawing pad. Someone contributed this one. So this is using Canvas to go ahead and do sort of multiple people drawing in the same pad at the same time, which is kind of nice. And we have chat, but chat is basically what turned into Java. So I'm not going to bother showing that. So connection status is interesting. So I talked about the fact that we do connection intrinsics for you. We manage connect and disconnect. We also have the concept of reconnect. So some of these transports aren't truly persistent. So WebSockets is a persistent connection. It's bidirectional, it's open. You can send stuff both ways and it stays open. But all of the other transports aren't actually full duplex. Service and events in Forever Frame will keep a connection open over which the server can send stuff to the client. But the client, when it sends to the server, it just makes an Ajax post. And we sort of hide all that under the layers for you. So what happens when the underlying receive channel goes away? I mean, it's the internet. Sometimes things go bad. So we have built-in retry logic. So if the connection goes down for whatever reason, we'll reconnect and we'll continue trying to reconnect until the server comes back up again. Now, by default, well, until last night, I was just looking at the check-ins and we've actually changed this behavior, we used to have, we do have the concept of a time-out, so you can actually set a value that says, keep the receive channel open for this amount of time and then forcibly close it, forcing the client to reconnect. That can be useful in certain situations, depending on what your load balancing infrastructure is like. But now we actually have the idea of Keep Alive. So by default now, from source anyway, not in 0.50, but in 5.1, we have a Keep Alive packet that will be sent. So while that connection is open, we will ping from server to client an empty payload just to keep the connection open. And that will trick load balances like those used in Azure and App Harbour and those type of things to not terminate the TCP connection. Because what we find is that a lot of hosting companies, their infrastructure for sort of handling connections, if they see a connection that isn't doing anything for a period of time, they'll just abort it. And so you have to be able to keep sending information over that, like a heartbeat ping, to keep that connection open. So we do that for you by default now in 0.5.1, which will be out very shortly. So because we have Keep Alive now, this actually won't drop. This will actually stay open. What you would see is if it reconnected, if it did drop, we'll go ahead and reconnect for you. And we will raise that event to your code so you can handle reconnect if you want to, but most of the time you don't have to worry about it. The thing will just reconnect. And you can see here that as soon as I disconnected on this side, I got the red saying that I left. So we handled that disconnect for you as well. Disconnect is a really, really interesting issue. Detecting when someone disconnects from your web server is actually really, really difficult, because there is a lot of different ways people can disconnect. So the reason that worked so well this time is we recently added support for graceful disconnect. So when we actually listen to the events in the browsers that support them that say the person is navigating away from this page, like the window on Unload, and if it does, we will try and send a packet to the server saying this connection is about to be closed. Because if you hit F5, what you're basically doing is killing one connection and then reopening another one. Connections don't last beyond pages, of course, because they only open as long as that JavaScript is running. And so when I navigated away from that page, you can see that I got disconnected on the left-hand side because we sent a packet to the server saying I disconnected. If for some reason that packet wasn't able to reach the server, then we have a background thread that runs on your application on the server that does know about all the connections for that server, because you might be running in a web farm, and will every 20 seconds or so check every single one of those connections and see whether the client is still connected. So IIS does have the concept of is client connected? There's a property on the response object. You can check if the client is still connected. And if that's false, then we look at some threshold, and if you're over the sort of the disconnect threshold, then we'll go ahead and fire the disconnect event, raise that up to your code, and you'll be able to do whatever it is that makes sense in your application for when you use the disconnects. Now, when talking about reconnect, that kind of suggests that there's a period where connections aren't open. And so what happens if messages are sent to the user while your underlying connection isn't actually open? It's a little bit hard to demonstrate, but you can imagine here that, let's see if I can actually demonstrate this. Let's see if I can put a break point. So the server is sending messages, and we can see on the left-hand side the one that isn't going to get broken here. So I'm going to come over to my...where is it? I'm going to come over to...resources, thank you. No, that's not what I wanted to... I'm in Canary, which is what's making this difficult. It looks like it's different. Let's come over to here. Okay, scripts is what I wanted. Let's come over to SignalR. So we can see this one. Let me just shift these around so I can see them a bit better. So the one over the left is going to keep running. Drag...no...oh, this is not looking good. Let's try that again. Where is that? Ah, now I've lost it completely. That one is that one. Let's put that one there. That one is that one. Okay, let's pull that one off. There we go. Put that one over there. Okay, so what we want to do is find the transport logic that's going to handle events. So here's service and events. I know that's what I'm using. I'm actually using WebSockets to process messages. Transport...da, da, da, da, da. Here we go. So I'm going to put a break point here. Okay, so I'm broken. And so over here, you can see the left-hand side is still getting messages. And the right-hand side isn't. Well, you can't scroll, but you can assume that it's not. And now if I hit play and I get rid of that break point, we'll see that I didn't miss any messages. I got all the same number of messages. So you can see 21, 23, 25, 27, 29, 31, 33, 35. It goes up by two every single time. I didn't miss any messages, even though that connection wasn't open at the point that those messages were coming through from the server. And that's because on the server, we buffer messages. So we have an in-memory buffer so that while connections are in their sort of their reconnect phase, where they're trying to reconnect again, we'll store those messages in memory. And then when the connection reconnects, it always says, hey, give me every message since message 47. Because that's the last one I got. And then if the message is since then, we'll send those messages down and the connection will go in its merry way. So that's how we handle reconnect, which is kind of nice. Okay. Scale out. So one of the questions that most people ask, first questions that most people ask, is usually two. How does it scale? Like, how many connections can you support? And how do you do scale out? Well, I'm glad you asked. Let's have a look at that. So we built SignalR with the ability to scale out in mind from the very, very beginning. So that's why we don't store state, like a list of connections which we enumerate over to do stuff. What we do do is base things on a PubSub mechanism. And so all you need to do is have some type of message backplane across your web farm that you can use so that if you've got one server here, another server here, you've got 100 people connected to this server and 100 people connected to that server, if I broadcast from server one, I want to make sure that all the people on server two get that message as well. You need to have some type of common backplane for that to work. And we currently ship two backplanes that we support. One is Redis. So who's used Redis at all, anyone? Oh, no one has used Redis. Wow. Is everyone here a.NET programmer, I'm guessing? Yes, that's why you've not used Redis. So Redis is an in-memory database that's very popular in sort of the Linux world. But MS Open Tech, the new open source subsidiary of Microsoft, has released as its first open source project a port of Redis for Windows. So we have a Redis provider for SignalR to do scale out and we have an Azure service bus provider. So if you're deploying SignalR in Azure with multiple nodes, you can plug it into Azure service bus as the backplane for the messages between your nodes. So let's use Redis because I'm just running on my local bus, my local machine here. So I'm going to come up to my app start. And you'll note that I already have an app start method set up here ready to go. I just got this commented out. So I've already installed a package called SignalR.Redis. So I just go to newget, install SignalR.Redis, which is going to pull in the bits that I need to use Redis and SignalR into my project. And then it's going to add an extension method hanging off our I dependency resolver type that says useRedis. And so all I have to do is pass in the address to the Redis server, the port, the password if there is one, and the event key I want to use to sort of segregate my messages for this app. And that's it. And so if I build that, I now have to go off and obviously start Redis because my Redis server isn't running. So let's do that. So this is PowerShell. I've literally gone to GitHub. I've cloned the Redis for Windows repository from GitHub and I built it using Visual Studio. OK, it's C++. I just upgraded it from 2010 to 2012. And then I built it. And then I went to the debug folder and I'm running start process Redis.server. So now Redis is running on my box. It's running on port 6379, which is good because that's what I configured it for, 6379. So that's good. And then what I'm going to do is I have another command over here, which is going to kick off, where is it? This one. I'm going to start my web farm. So it's not good doing scale out unless I have more than one web server. So here I have two web servers. I've got IS Express on one side listening on port 8090 and then IS Express on another side listening on port 8091. So let's kind of reorganize all these windows so this makes sense. So here we go. This is sort of a visual idea here. We have one server on the left, one server on the right. Redis in the middle. OK, that's kind of cool. So let's go ahead and connect some clients to this. So let's get my browser running. Let's get one browser connected to... Let's see if I can do the resize shuffle here. Get one browser connected to a local host. I want this to go to 8090 slash move shape. So that you can see over here that IS spat out some stuff saying that things are happening. So let's open another browser and move that one over here. And we'll connect that one to the other web server. So you can imagine that I was in front of... I have a load balancer, right? And I'm actually just going to the same address. And now when I drag, you can see that it's working. So a little bit lagged this time. And it looks like I killed something. Demo fail. Oh, there we go. It's just lagging. My machine is getting a little bit wacky. You can see it did catch up. So even though it lagged, it did actually eventually catch up. All the messages got through. So now that it's warmed up, it's actually working quite well. So I now have two completely different web servers. So my application is running twice in two separate processes. So there's nothing shared between these processes. And all the cross-process communication is happening through Redis, which is kind of cool. Now, the one thing that isn't working, as you can see, is my connection count is wrong. So can anyone tell me why my connection count is wrong? I didn't saw that in Redis. Remember, it was just in a static dictionary. So I've got a connection count of one in each server, which is correct for each server. But obviously, if I was writing this app to be scale-out-friendly, I'd have to put that sort of information in some type of back-end, either in a Redis store or a C-consever or something like that. But that shows you just how easy it is to get scale-out working with SignalR using something like Redis. Okay, so that's kind of cool. So that's one of the questions answered that people always ask, which is, how do I do scale-out with SignalR? Well, you can. The other question is usually around load and scale. How many connections can you support? Well, I can tell you that, well, and we take this very, very seriously, where we obviously want SignalR to be as performant as it possibly can be and support as many connections as it can. With the current build on my machine at home, which is a Core i7-920, which is like a first-generation Core i7, it's about three years old, so it's not a new machine by any stretch, but it's quad-core, hyper-threaded, so it's a decent machine, but you could build one today for four or 500 bucks. I can, with 5,000 clients broadcasting at 10 or 20 messages a second, get about 30,000 cents per second in that infrastructure. So that's pretty good. And a three-year-old machine getting about 30,000 cents per second for 5,000 clients. Our bottleneck at the moment isn't CPU. In fact, the CPU doesn't max out during that test. Our bottleneck is contention. We have a fundamental flaw in our Core architecture. In 0.6, we're going to be re-implementing the Core of SignalR, excuse me, to change how we sort of do our Core level PubSub infrastructure, and we expect that number to drastically improve. So we've got some very smart people on the ASP.net team, much smarter than me, building custom data structures for doing message management at the moment. So as I said, we have an in-memory message store, and at the moment we have some issues with garbage collection because messages live for a while before they go away. So while it works very, very well, and when you get under really, really heavy load, like crazy heavy load with thousands of messages a second, you can certainly run into issues. We have new message stores, infrastructures, which can do millions and millions and millions of messages a second without breaking a sweat. So over the next four to eight weeks, we're going to integrate that into the Core of SignalR, and in 0.6, you should see the benefits of that. And as I said, we'd certainly expect the throughput numbers to at least double, and if not triple. So I'm certainly shooting for hopefully six-digit sort of messages per second throughput on my setup at home. But that's all good. That's just talk. Let's get a low test up and running here right now so you can sort of see how this works and what tools we use to do our low testing. So we have a performance harness for SignalR that we wrote called Flywheel. We have these crazy names. I don't know how it started. I think it started when David wrote a load generation tool called Crank. And so I thought, great, Crank's connect to Flywheel. So I'll create a harness called Flywheel. And then within Flywheel, we'll have a class called Shaft, because Crank connects to the Shaft, which is on the... Anyway, so we have these silly names. We're running out of engine parts to call stuff, so it's not going to scale very well. So we have this thing called Flywheel. And if I run that up, what you'll see is it's a dashboard, essentially, that spits out real-time information about what's happening on the server, like how many messages are being sent through the message bus at the moment, and graphs sort of the number of sends and the average sends per second. So that's kind of cool. And then from here, I can control how many broadcasts I want to do. So obviously, there's no one connected to this at the moment, because it's just me. I haven't created any client load yet. So setting broadcast rate of 5 per second isn't really going to do an awful lot. But we'll see how we do that in just a moment. So I can set the broadcast size, I can set the broadcast rate, and I can say what I want to do when the Flywheel receives messages. So we also have in Flywheel something called Mini Crank. Let's try that again. Mini Crank. So Mini Crank is a page that connects to Flywheel, connects to Shaft, and then says, I can say go ahead and send a message every 100 milliseconds. So I'm now sending a message 10 times a second. And so what we should see now, if I say, well, on receive, I'm going to echo, we should see our send per second rate go up. You can see it did, because it's echoing back messages as it receives them. So that's kind of fun, but it's only one client, so that's really not that interesting. Mini Crank is really not very useful for doing load, it's just useful for testing that the harness works. What we need to generate load is a real load test generator. And so it's likely enough the IAS team builds one of those, it's called WCAT. Anyone used WCAT before? Okay, like three hands, let me quickly show you WCAT. So WCAT stands for the Web Capacity Analysis Tool. Great name. Let's make the X64. Make sure that most people are measuring and running 64-bit machines now. So when you search, make sure you search for X64, because the first page results otherwise won't show the 64-bit download. It's kind of strange. So you want to download WCAT 6.3 and install it. It'll just run on any Windows box. It's a native XE and some scripts that you can use to generate load, HTTP load. Now, so while this isn't a signal or client, I can make it do enough to make it generate load like a signal or client, or at least listen to signal or broadcast, which is all I really care for doing load testing. And so let's go back here and let's look at my WCAT setup. So this is all available as well. So we have a repository up on SignalR. So I didn't actually tell you where it was. Up on SignalR on GitHub. So here's github.com. So I go back up to SignalR. That was way too many SignalRs. There is a, here's Flywheel, which I just showed you, and here's Crank. And in Crank, we have a folder called WCAT, which contains all the settings files, which I'm about to show you, that you can use to generate load against SignalR using WCAT. So here's my WCAT folder. If I look in settings, most of this stuff is just copied from the WCAT samples and then tweaked. So I'm going to emulate 1,000 clients. So I'm going to have one physical client and then 1,000 virtual clients. So 1X year is going to be 1,000 people. So WCAT has the ability to have a controlling WCAT server and then multiple WCAT nodes. And then each WCAT node will be a client. So you can make that client 10 if you have 10 client machines. And then you can say each one of those client machines is going to emulate 1,000 virtual clients. And then that one WCAT server will control all the client machines. It's actually a really, really cool little tool. But I'm just doing this all in one box for the sake of a demo. So then I have a scenario file. So I have this shaft scenario file because I'm going to connect to shaft. And you can come down here and you can see that I'm going to connect to port 29573. And this is the URL I'm going to connect to to make it look like a signal receiving connection. So here's that connect phrase that we saw before when we looked at the network stack in Chrome. And I'm going to use the forever frame transport because it doesn't matter. I mean WCAT doesn't support WebSockets. So I just have to use either service end event or forever frame. So I use forever frame. And then I'm setting the connection ID to whatever the current virtual client index is. So vClient index is just a function provided by WCAT to get the current number of this virtual client. Okay. So I have a batch file that sort of runs all this together. So it runs the WCAT script with all the parameters that you need to make this thing run. WCAT isn't a user friendly tool. Let me just tell you that. It's quite finicky to get running. So it is well documented. It does have a fairly large word document, but it is a learning curve. So it's nice to be able just to get some scripts that work and then run it. All right. So we have, let's find my WCAT. There it is. So we have flywheel running. Let's see if it's still there. There it is. Okay. Let me pull that out. Let me pull that down there. Let's minimize that one. Let's put that up there. Let's come here. So currently I have no clients connected. You can see over here, no clients connected. Clients is zero. So let's start up WCAT. Okay. So WCAT is starting. So we can now see that connected clients are coming in. You see it's starting one virtual client every so many microseconds. So I'm going to go up to a thousand clients. So now it's sort of in its listening mode. It's still starting up clients. I'm going to get to a thousand. Okay. So now I'm going to start broadcasting. So let's broadcast at five messages a second. And what we should see is that I get about 5,000 cents per second because I have a thousand clients. I'm doing five broadcasts a second. So that's 5,000 cents per second going through the system. And indeed, so far, this machine is able to cope with that, without any problem. We don't start running into that contention limit that I talked about in our core of our architecture at the moment until you get to about 30,000 cents per second. And this machine wouldn't be able to handle 30,000 cents per second anyway. So you can see the CPU use, you know, is pretty high. It's actually, funnily enough, a lot of it is drawing this graph. If I look at the process, that's crazy, I know. If you look at the CPU, look, Chrome is using 38% of my CPU. So test, just a little lesson. Don't run everything on the same box when doing low testing. Don't run your dashboard on the same box as your server because drawing pretty graphs with Canvas on SVG takes a lot of CPU cycles on the browser. So you can see my web server, IAS, is actually only doing like 40%, 30 to 40%. And so it's actually the browser that's taking up most of the rest of the CPU at this time. So that's going to run for, I think, 90 seconds, is the test duration. So we'll just let that run because I want to show that what's going to happen when the test finishes as well. So you can see there's been no errors. WCat will keep spinning out all the stats every 10 seconds from the last 10 seconds. Now, because these connections never end, nothing comes out. Usually WCat just makes requests, and then as soon as the request comes back, it makes another request again. It's designed to generate load, right? But I'm using it to simulate persistent connections. So it just makes the connections, and then because I never end them, they just stay open. And WCat just sits there going, OK, connection's open. I'll just keep it open and just keep spinning out empty stats. WCat's fantastic because it has virtually no memory overhead. It's a native client. It happily receives everything I send to it from the server and then just throws it away again. It just uses no memory. It's fantastic. Incidentally, I did manage. I'm using a 32-byte payload here. On my infrastructure at home, I have a dedicated gigabit switch, and then I have a separate machine that I use to emulate the clients. And so when I ran that machine with 1,000 clients against my server through my dedicated gigabit switch with a 4K message size, I was able to saturate the gigabit nick on the client machine. So that's always a really, really good indication of your low test. If you can saturate the nick, that's good. That's really, really good. It means that your bottleneck isn't CPU or memory or anything else. So the test is finished now. You can see nothing is sending anymore. No one is connected. So if I scroll over, we should see I still have people who are connected. So remember I said there's the idea of a graceful disconnect and a non-graceful disconnect? So WCat finished, but it doesn't know to send that packet that signaler understands that the connection went away. So the connections were still alive on the server until such time that our background process came around and realized that they were dead. And you can see that that happened. So at this point here, our background process realized those connections were no longer there and would fire the disconnect event for all of those connections. So even though WCat weren't gracefully disconnect using a signaler, graceful disconnect, we came ahead and cleaned up those processes without any problem. So interesting point in terms of scale and RAM. I've talked about CPU and I've talked about connection. I've really talked about RAM. Where's my IS express process? Do it that way. Okay, so that's probably the one. I'm assuming the one that has all the memory. 100 meg. ASP.net has out of the gate about 40 to 50 kilobytes of managed heap size overhead per connection. I'm not going to lie to you. It's fairly heavy. So once we fix the sort of contention problem that we have in 0.5, which we'll fix in 0.6, your major limiting factor for scale is going to be memory. So we have actually driven signal up on a single box to 100,000 concurrent connections. And I think it used 40 gigabytes of virtual memory or something crazy like that. Because of this sort of limit in ASP.net. Now we are working on in 4.5, things have improved. And if you're using web sockets on 4.5 on Windows 8, that overhead is drastically decreased to like single digit kilobyte overhead per connection. And so it does get a lot better. But you can host signaler outside of ASP.net. Signaler is not an ASP.net library. It's a.net library. And we are host agnostic. The default setup when you new get in signaler is host on ASP.net. But you can host on whatever server you like. And indeed in 0.6, we're going to standardize on OWN as our hosting layer intrinsic. So if you want to host on a different server, like self-host using hdb sys, or a socket server like flywheel or kayak, which are open source C-sharp web servers, you can absolutely do that because we'll support OWN and those things support OWN. So you'll just be able to host signaler on top of whatever it is that you want. And there are people in the community who have already written custom signaler servers in order to do their own hosting from within their own XE. Now again, I think 99.99% of people who use signaler are going to use it in ASP.net and they'll never have to worry about that. But if you're going to be doing really, really high concurrency, lots of clients per machine sort of deployments, then a custom server might make sense if you're not going to be using WebSockets just because of the memory benefits that you'll get. You'll be able to support more connections per server, which is kind of cool. Okay, so we're nearly out of time. I've pretty much shown everything I wanted to show. So we have two minutes left for questions. Anyone have any questions? Yes? Mobile clients. What's that? Sorry? Mobile clients. Mobile clients. The question is mobile clients. Do we support them? Yes, we do. So if I go up to GitHub and we look at the repository, you'll note that we have a bunch of clients by default. So there is clients for Windows Phone 7, clients for Silverlight. The JavaScript client is just in the signaler library. There's a client for Windows 8, Metro apps. And there's a client for.NET itself. So if you're just using like a WPF app like I did that's an audit client. The community has contributed an iOS client. There's an iOS client that someone else maintains. There's a MonoTouch client that someone has built. There's a Java client I believe someone has built. Someone built a Node client. I have no idea why, because Socket.io is great. Use Socket.io if you're on Node, but they did. And I believe there's a MonoDroid client as well available. Now, our current thoughts for version one of SignalR is we would like to have all those clients sort of built by the team and supported. Because we think SignalR is much more attractive the more clients it has. So look to see, ask, pull those clients in or build new versions of those clients for version one whenever they get down. Any other questions? Yes? So the question was what about T4 templating instead of generating the script dynamically? So one of the problems with generating the hub proxy at runtime is you don't get IntelliSense on the hub in Visual Studio. It's kind of nice in JavaScript if you can get that. We do have some prototypes of that and it is on our backlog to support design time slash compile time generation of that file so that you'll get IntelliSense. I do believe actually something has already checked in that does that. I'm not sure that it uses T4. I think at the moment it uses an XE so that you can just run that from inside your build file so that it'll just build the JavaScript file and jump it into your project. And you'll just reference that JavaScript file rather than that magic route that I showed you before. So yes, we are working on that. Yes? I've seen on iCat for instance you get the constant loader. Yeah. Is that something you know? So the question is on some clients with some of the transports you get the little loader spinny to stays there forever. It's a registered issue. We're looking at it. The current fix that we have that we're testing out is just to delay the creation of the transport with a set timeout. So rather than doing it immediately just say set timeout 250 milliseconds and then create it and that seems to fool the browser enough. It seems crazy that a browser would support service end events and then show the spinny while the thing is open but they do. Some of them, iOS in particular. So we are going to fix it. Yes? Yep. Right. So I think, let me rephrase, the question was about graceful disconnect and IE and IAS and about what combination is required to support the graceful disconnect? Right. So IAS has this ability to asynchronously notify your code when a client disconnects, which is nice. Now that's not graceful disconnect. Graceful disconnect in a signal our terms is when the signal our client tells the server I'm about to stop the connection. So any browser that will run our code on window unload and let that Ajax request go through will support graceful disconnect because then we'll just receive an Ajax request on the server that is a disconnect command and then we'll disconnect the client in our server. If that doesn't get received and there's a couple different ways that we can detect the client is disconnected. IAS 7 and above gives us this is the, IAS 6 and above gets us this is client disconnected property on the response object that we can essentially poll. So every 20 seconds we check the connection and say is client disconnected false? Oh it is. So the client is now gone. Let's see if it's over the disconnect threshold and then we'll disconnect them. In ASP.net 4.5 we've added if you went and saw my talk this morning there is a new asynchronous notification you can subscribe to to get told when the client goes away because IAS 7.5 or above supports this and so if you're using ASP.net 4.5 on IAS 7.5 you'll be able to subscribe to a cancellation token on the request object that will fire when the client shuts down or closes the connection. Assuming that that gets to you know because underlying the TCP level connection there will be a message sent up to the server and IAS will bubble that up asynchronously to your code. So we do our best whether it's graceful or disgraceful, no that's not right, graceful or not disconnect to try and notify your code that a client has gone and do it in the most timely manner that we can and try and ensure that we only do it once. That was a big problem in disconnecting web farms that we didn't fix until 0.5 is how do you handle the fact where I connect to server 1 and then I reconnect to server 2 now server 1 is going to fire a disconnect event. So we had to handle we have to have cross node collaborations such that when you connect to server 2 server 2 can tell all the other servers hey I now own connection 1, 2, 3, 4 everyone else just forget about it don't fire the disconnect event. So that's what we added in 0.5 to make disconnect work in web farms properly. So I'm out of time but I'm happy to keep answering questions while people are still here because it's 15 minutes until the next guy so. Oh actually it's only the party now so I'm just keeping you from drinking so if you want to know more I can do that but thanks for coming along and try it out.
library for Node that builds on top of Socket.io really easy to get going with signalr doing these actually an API that you can use in the browser connection abstraction gives you connect and often get when talking about SignalR is, how do I request. So I'm in a browser that supports WebSockets is a persistent connection. It's making this difficult. It looks like it's