Challenges Developing Realtime Web Apps

1,148 views

Published on

As HTML5 and the surrounding API´s has matured and grown in popularity we see more and more web-applications being built for mobile devices replacing old native applications.

In this article I walk through some of the challenges we face when developing real-time web-apps and also show one of the many ways to overcome these challenges.

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,148
On SlideShare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
8
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Challenges Developing Realtime Web Apps

  1. 1. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo Challenges Developing Realtime Web Apps As HTML5 and the surrounding API´s has matured and grown in popularity we see more and more web­applications being built for mobile devices replacing old native applications. When we first saw the specifications of HTML5 we realized that the “era” of the native applications was over... There are still lots of occasions where developers choose native instead of web, but I think that we all can agree on the fact that HTML5 has taken native applications out of its glory days. So this HTML5 thingy have to be awesome then... The holy grail... Well, not really... HTML5 is awesome, but we now face new challenges when developing our precious web­applications. In this little article I will try to point out some of the challenges we face developing real­time web­applications and also show how we try to solve them. Some background... Over the last 6 months we have been receiving questions/statements such as... “We are replacing our old native app with a new web­application, we will use websockets and have some basic demands...”. “We want to send messages to specific clients based on user properties such as location or a technicians specific skills”. And also... “If the client is offline or out of range (network) we want the messages to arrive when he/she gets reconnected”... The two demands/questions above is not trivial to solve, especially not if you are starting from scratch building your own websocket solution. Fortunately most developers will not have to do so.. There are several great frameworks out there that will help you along the way. To know what framework you and your team should use I say... Do proof of concepts with a few of the candidates, even though they look alike on the surface there are huge differences in what you get. There are quite a few options out there and I will list some of them objectively below without any specific order. Name Service Self Hosted PubNub X Pusher X SignalR X Socket.IO X SuperWebSocket X
  2. 2. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo Fleck X Realtime.co X XSockets.NET X Autobahn X Note: Another good resource for realtime framework is Phil Leggetter and his RealTimeTech Guide http://www.leggetter.co.uk/real­time­web­technologies­guide For this guide I will use XSockets.NET, and if you know me that will not be a surprise since I have been working with XSockets since 2010. Even though my choice is XSockets I would encourage anyone out there that is a specialist on SignalR, SuperWebSocket, Socket.IO etc to build your version of the code I produce. That way it gets easier to compare between frameworks when building this non trivial but commonly demanded functionality. From here on we write code :) I will keep it simple and have all code inside of a ASP.NET MVC project event though XSockets can be installed into a separate project it is easy in development mode to run everything in the Visual Studio development server. I think the world has seen enough websocket chats already, but I will create yet another one ;) The big difference here is that... ● we will be able to target clients based on the location ● messages sent while a client was offline will be sent when he/she gets back And of course the goal is to solve this without inventing the wheel once again... Create a new MVC project I will create a MVC3 project and name it GeolocationBasedChat and then delete all folders and files except from the global.asax and web.config. Install XSockets
  3. 3. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo To install XSockets open up the package manager console (tools ­> library package manager ­> package manager console). Type “Install­Package XSockets” and hit enter The installation gave you... ● A bootstrapper for XSockets under App_Start ● The required assemblies/references ● The JavaScript API of XSockets ● Some scaffolders (out of scope here) Change some settings in Visual Studio In this example I will only use a html file for the client, this means that Visual Studio will not fire up server side stuff by default. Therefor I... ● right click on the project and select properties. ● select the “Web” tab ● select the “Use Visual Studio Development Server” under the “Server” section This will now fire up the XSockets server even if we do not request any server side resources. Part 1 - Server side - Create a real-time controller In the first part of the server development we will only add a new real­time controller and some properties. The easiest way of creating a new controller is to use the scaffolder from the package manager console. This can scaffold controllers into new projects and reference the new project, but we will settle with a new controller inside of our GeolocationBasedChat project. Open the Package Manager Console and type... Scaffold XSocketController XControllersChatController This will add a new class (ChatController) under a new folder (XControllers) in our default project.
  4. 4. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo We will now be able to connect to this empty controller. Part 1 - Client side - Testing the connection Our new real­time controller names ChatController have no action methods, but we can test the connection. In the root of our web add a new html file (default.html) and then add some JavaScript reference and a few lines of code to test the connection. If you right click the default.html, select “view in browser” things should fire up. Then if you open the console (ctrl + shift + j) in Chrome you should see something like.
  5. 5. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo Part 2 - Server side - Add action method Now we know that our new controller is working, so the next step is to add a server side method to call from our javascript. We will add a basic version to start with and extend it later in the article. So.. add a method named SendToRange with the following signature in the ChatController class. This will obviously send the message to all clients. However one important thing to know about XSockets is that the server does not broadcast to all clients connected to our ChatController... It will only send to clients subscribing to the “sendtorange” event. The reason for this is that we do not want to send anything over the wire that the client does not want (does not subscribe to). Part 2 - Client side - publish/subscribe After this section we have a simple chat, that will send messages through our action method to all subscribers. Changes to the previous version of the client are marked in yellow.
  6. 6. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo The first section creates a subscription for the “sendtorange” event and prepends a div to our “messages” element when a message is received. We send in and return a string so we can just output it directly. The second section just listens for a click and triggers (publishes) a message to the “sendtorange” method. And finally some markup at the bottom... Part 3 - Server side - Geolocation So far we have not done anything unusual in the world of real­time, but remember that one of the demands was that we wanted to send to clients based on some property or location. So lets go for location :) We will try to send messages to clients based on the city they are currently in. Since I do not want to do any GeoLocation stuff in the client we will set coordinates based on the city the client says he´s in.
  7. 7. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo We will now need a property for Geolocation, so let's add a reference to the System.Device assembly since that will help us with the calculations of distance :) When the reference is in place add some code... We added... ● A property for City ● A property for having a coordinate ● A “dummy” method that gives us a coordinate from a city since we do not send coords from the client ● A call in the constructor setting the default city to Madrid ● IMPORTANT: note that we changed SendToAll to a SendTo<T> with a lambda expression. We would of course use the geolocation API instead of fixed coordinated in real life, but that is out of scope for the article. The usage of goelocation would make the dummy method “SetCity”
  8. 8. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo and the constructor call to it obsolete. Part 3 - Client side - Location selector Now, since all clients will get the same city (Madrid) we need to provide a fake city selector in the client. We will just add a drop down and send a new city to the server when the client changes the selection. As you can see we only added a dropdown and a event listener that triggers the setcity method in our controller. So if we run the example now we will be able to filter where to send messages based on the selected city, but we are not quite satisfied since we also wanted to target based on distance... We will get to that part soon..
  9. 9. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo Part 4 - Server side - Sending to clients within x kilometers Since we added a reference to System.Device and have a GeoCoordinate on our controller we can use the “GetDistanceTo” method of the GeoCoordinate to select the clients we want to send to. Once again the changes are displayed in yellow marking. You can see some minor changes that have a huge effect. by passing in a range we can say “Send this message to everyone within the range of x kilometers from my location”. But so far we do not set the range.. That would be our next step. Part 4 - Client side - Decide how far our message will travel As you just saw we added some code that decides how far from the clients location the message will travel. So in our client we want to be able to select a city to get coordinates, and we can already do so. Now, we also want to pass a range parameter so that we actually can send messages to other cities (if they are within range).
  10. 10. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo By adding a input of type range and passing the value of the input to our “sendtorange” method we can now target clients in other cities. Before we were targeting clients based on the “City” property, but now we can decide how far to send the message based on the range in the UI. If you try you will see that the distance between the cities is something like... ● Stockholm to Paris ­ Between 1500 ­ 1600 km ● Stockholm to Madrid ­ Between 2500 ­ 2600 km ● Madrid to Paris ­ Between 1000 ­ 1100 km What do we got so far ? Well, we have our selves a really ugly (UI) looking chat, but we can send messages to clients
  11. 11. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo within a range that we decide our selves. So if we look back to the beginning of the article we have only solved the part where we want to send messages based on properties such as geolocation. Now we have to solve the part where the clients should receive messages that was meant to target the client but was sent when the client was offline. Part 5 - Server side - Store and deliver messages for clients being offline This can be done in so many ways, and you can also do it in a very advanced way. The approach I will take will use a QueueHelper in XSockets, by QueueHelper I am talking about a in­memory message queue that is generic and target a specific Controller. The idea is the following... 1. When a client disconnects we tell the queue to store all messages for one (or more) events. 2. When we send a message (this.SendTo, this.Send, this.SendToAll etc) we send the message to the queue. 3. When a client connects it asks for all messages that arrived while he was offline. The first thing I do is to create a custom extension for XSockets Controllers. This is not necessary, but since we need to send to all connected and then send it to the queue a helper will make the code a little bit nicer. , The above takes care of number 2 in our list above, now we need to take care of the connect and disconnect events.
  12. 12. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo As you can see above we use the connect and disconnect events to handle the queue, and we also replaced the SendTo method with a call to our new extension that both sends messages based on a Func<T,bool> and then sends the message to the queue. Summary Hope you made it all the way down to this summary :) If you did I hope that you enjoyed the article. You do not have to agree with me that this is THE way of doing things. I just wanted to show one of the ways of doing this. We at XSockets know that having state on our controllers is a unusual way of doing things, but we actually like the benefits with the really easy programming model and the small amount of code needed to accomplish pretty advanced scenarios. As I said in the beginning of the article, please write similar posts on how to do this with other frameworks. I know XSockets and thats why I used it here, but I am eager to see how you do it with other frameworks since I know that I will learn alot from it and hopefully get some new ideas/improvements for XSockets.as well. The sourcecode for this article can be found at http://github.com/codeplanner/geolocationbasedchat
  13. 13. Uffe Björklund 2013­07­15 uffe@xsockets.net @ulfbjo Regards Uffe Björklund @ulfbjo

×