-
1.
SignalR.
Code, not
toothpaste Maarten
Realtime client/server Balliauw
Technical Consultant
communication RealDolmen
@maartenballiauw
-
2.
R
-
3.
Who am I?
Maarten
Balliauw
@maartenballiauw
-
4.
Why real-time & how?
Meet SignalR
Connections and Hubs
Clients
Q&A
-
5.
Why real-time & how?
-
6.
Twitter – live searches/updates
Stock streamers
Auctions
Live scores
Real-time notifications
Interactive games
Collaborative apps 6
Live user analytics
…
-
7.
Never designed for real-time communications
HTML5 WebSockets to the
rescue, right?
-
8.
Extension to HTTP
Provide raw sockets over HTTP
Full-duplex
Traverses proxies
It’s still a draft…
Not every proxy server supports it
Not every webserver supports it
Not every browser supports it
They are raw sockets!
-
9.
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
<script>eval("... ")</script>0
<script>eval("... ")</script>0
-
10.
Fiddler
hootsuite.com
Polling interval
-
11.
Fiddler
facebook.com
-
12.
Options!
Forever Frame
Periodic polling
Long polling
HTML5 WebSockets
(Server-Sent events)
-
13.
ARRR!
Meet SignalR
-
14.
Three-in-one!
-
15.
http://github.com/signalr/signalr
-
16.
where else!
http://amzn.to/xrzS6j
-
17.
Hello, SignalR
-
18.
BONUS DEMO!
-
19.
Connections and Hubs
-
20.
PersistentConnection Hubs
Can communicate with 1..N clients Can communicate with 1..N clients
Is an IHttpHandler Abstraction over PersistentConnection
Requires a route to be defined Route automatically mapped (/signalr/hubs)
Limited to sending messages Can send messages and call methods
You define the “protocol” SignalR defines the protocol
-
21.
Hello, SignalR
hubs
-
22.
http://jabbr.net
-
23.
Clients
-
24.
On the server side
On the client side
But there’s more…
-
25.
On the server side
https://github.com/SignalR/SignalR/tree/master/SignalR.SelfHost
On the client side
Is this a replacement for WCF?
-
26.
DeckCast
-
27.
SignalR is three-in-one!
Connections & Hubs
Connect various clients
-
28.
Make the web realtime!
Install-Package SignalR
-
29.
http://aka.ms/mbl-tech
http://aka.ms/mbl-tech/devprev
http://aka.ms/mbl-tech/html5
-
30.
Maarten
Balliauw
@maartenballiauw
Q&A
-
31.
http://blog.maartenballiauw.be
http://github.com/signalr/signalr
http://www.nuget.org/packages?q=signalr
http://github.com/signalr/signalr.websockets
http://vasters.com/clemensv/2012/02/13/SignalR+Powered+By+Service+Bus.aspx
https://github.com/DyKnow/SignalR-ObjC
https://github.com/SignalR/SignalR/pull/127
How do youimplement these today?
That’s a lot of options, a lot of thingsto account forand a lot of different programmingmodels. Are yougoingto do this?Are youstillwriting separategetDocumentByIdandAttachEventmethodstoworkwith the DOM? WhataboutjQuery?
Open VS2010Create a new ASP.NET Empty WebsiteInstall-PackageSignalRNote server library, client script, jQuery dependencyInstall-Package SignalR.Sample and show stock ticker in two browsersNowlet’s take things easy… How does all of thiswork?----------------- without Internet connection ----------------------------Add a class:public class TimeConnection : PersistentConnection{}Add a route:RouteTable.Routes.MapConnection<TimeConnection>("time", "time/{*operation}"); Addaninfinite loop:ThreadPool.QueueUserWorkItem(_ => { var connection = Connection.GetConnection<TimeConnection>();while (true) {connection.Broadcast(DateTime.Now.ToString());Thread.Sleep(1000); } });Addsome HTML:<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <title></title> <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script> <script src="Scripts/jquery.signalR.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { var connection = $.connection('time');connection.received(function(data) { $('h1').text('The time is ' + data); });connection.start(); }); </script></head><body> <h1>The time is now!</h1></body></html>----------------- without Internet connection --------------------------------------------- with Internet connection ----------------------------Install-Package LinqToTwitterAdd a class:public class TweetsConnection : PersistentConnection{}Add a route:RouteTable.Routes.MapConnection<TweetsConnection>("tweets", "tweets/{*operation}"); Addaninfinite loop:ThreadPool.QueueUserWorkItem(_ => { var connection = Connection.GetConnection<TweetsConnection>();while (true) {using (TwitterContext context = new TwitterContext()) { var tweets = context.Search.Where(t => t.Type == SearchType.Search && t.Query == "#test").SingleOrDefault().Entries;connection.Broadcast(tweets.ToList()); }Thread.Sleep(5000); } });Addsome HTML:<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <title></title> <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script> <script src="Scripts/jquery.signalR.js" type="text/javascript"></script> <script type="text/javascript"> $(function () { var connection = $.connection('tweets');connection.received(function (data) { $('#tweetsList').html('');for (var i = 0; i < data.length; i++) { $('#tweetsList').append($('<li>' + data[i].Content + '</li>')); } });connection.start(); }); </script></head><body> <h1>Tweets</h1> <ulid="tweetsList"></ul></body></html>----------------- with Internet connection ----------------------------Notice we are sending data TO the client?
TweetsusingKnockoutJS
Open the previouslycreated sampleInstall-Package jQuery.UI.CombinedAdd a class: [HubName("worker")] public class WorkerHub : Hub { public voidstartProcessing(Event e) {Caller.notify("We'vestarted processing " + e.EventName);Clients.setProgress(10);for (int i = 0; i <= 100; i++) {SignalR.Hubs.Hub.GetClients<WorkerHub>().setProgress(i);Thread.Sleep(100); } } }Addsome HTML:<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml"><head> <title></title> <link rel="stylesheet" href="Content/themes/base/jquery.ui.all.css" /> <script src="Scripts/jquery-1.6.4.min.js" type="text/javascript"></script> <script src="Scripts/jquery-ui-1.8.16.min.js" type="text/javascript"></script> <script src="Scripts/jquery.signalR.js" type="text/javascript"></script> <script src="signalr/hubs" type="text/javascript"></script> <script type="text/javascript"> $(function () { var workerHub = $.connection.worker; $('#progressbar').progressbar({ value: 0 }); $('#startWorkTrigger').bind('click', function () {workerHub.startProcessing({ eventName: 'UAN12' }) .fail(function (e) { alert("An error occured: " + e); }); });workerHub.notify = function (message) { $('#notifications').html(message); };workerHub.setProgress = function (progress) { $('#progressbar').progressbar({ value: progress }); }; $.connection.hub.start(); }); </script></head><body> <div id="progressbar" style="width: 200px;"></div> <div id="notifications" style="width: 200px;"></div> <button id="startWorkTrigger">Start work</button></body></html>
Create a new Windows Phone 7.1 project using the “WP DataBound Application”Install-Package SignalR.Client.WP7Uninstall-Package NewtonSoft.Json -ForceInstall-Package NewtonSoft.Json -Version 4.0.3In MainViewModel, remove the contents in LoadData(): public void LoadData() { if (!connection.IsActive) {connection.Start(); } }Add a field:private Connection connection; In the constructor, preparetoreceive data. Note the Dispatcherto make sure the adding of the data happens on the UI thread: public MainViewModel() {this.Items = new ObservableCollection<ItemViewModel>();connection = new Connection("http://localhost:6502/tweets");connection.Received += data => Deployment.Current.Dispatcher.BeginInvoke(() => UpdateItems(data));connection.Start(); }Add the UpdateItemsmethod:protectedvoidUpdateItems(string data) {this.Items.Clear();JArray entries = JArray.Parse(data);foreach (JObject entry in entries) { string content = Regex.Replace(entry["Content"].ToString(), "<.*?>", string.Empty);this.Items.Add(new ItemViewModel() { LineOne = entry["Title"].ToString().Substring(0, 12),LineTwo = ((JObject)entry["Author"])["Name"].ToString(), LineThree = content }); }this.IsDataLoaded = true; }
Open DeckCastShow peoplearoundandtellthemabout deck.jsShow the presenter mode andclient mode on the webStart a console based viewerStart the WP7 presenter app (focus/unfocus the “sample” box toconnect, click SLOWLY)