ݺߣ

ݺߣShare a Scribd company logo
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
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
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.
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.
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.
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.
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”
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..
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).
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
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.
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
Uffe Björklund 2013­07­15
uffe@xsockets.net
@ulfbjo
Regards
Uffe Björklund
@ulfbjo

More Related Content

Challenges Developing Realtime Web Apps