charles petzold networking
TRANSCRIPT
![Page 1: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/1.jpg)
Charles Petzoldwww.charlespetzold.com
Networking
![Page 2: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/2.jpg)
Agenda
• WebClient• HttpWebRequest• Consuming REST services• Consuming ASMX and WCF services• Push notification services• Tile scheduling
![Page 3: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/3.jpg)
Silverlight vs. SWP
Feature Silverlight SWPCross-domain networking
Requires elevated permissions or policy file No restrictions
Cross-protocol networking
Requires elevated permissions or policy file No restrictions
Networking stacks
Browser stack and client stack Client stack only
Duplex networking
PollingDuplexHttpBinding and NetTcpBinding HttpNotificationChannel
Authentication Basic, digest, NTLM, and forms Basic and forms
Sockets Yes Not supported
UDP multicasting Yes Not supported
![Page 4: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/4.jpg)
• Event-based HTTP networking API– Asynchronous operation only
• Commonly used to download assets– DownloadStringAsync - String– OpenReadAsync – Stream (binary)– Also features uploading methods
• Fires progress and completion events and supports cancellation of pending requests– Event handlers execute on calling thread
WebClient
![Page 5: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/5.jpg)
Downloading an Image File
WebClient wc = new WebClient();wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted);wc.OpenReadAsync(new Uri ("http://www.wintellect.com/images/Bandit.jpg")); ...private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e){ if (e.Error == null) { BitmapImage bi = new BitmapImage(); bi.SetSource(e.Result); MyImage.Source = bi; }}
![Page 6: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/6.jpg)
Downloading a Zipped Image FileWebClient wc = new WebClient();wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted);wc.OpenReadAsync(new Uri("http://www.wintellect.com/images/Images.zip")); ...private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e){ if (e.Error == null) { StreamResourceInfo sri1 = new StreamResourceInfo(e.Result, null); StreamResourceInfo sri2 = Application.GetResourceStream(sri1, new Uri("Bandit.jpg", UriKind.Relative)); BitmapImage bi = new BitmapImage(); bi.SetSource(sri2.Stream); MyImage.Source = bi; }}
![Page 7: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/7.jpg)
Updating a Progress Bar
WebClient wc = new WebClient();wc.DownloadProgressChanged += OnDownloadProgressChanged; ...private void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e){ Progress.Value = e.ProgressPercentage;}
![Page 8: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/8.jpg)
Downloading an RSS Feed
WebClient wc = new WebClient();wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted);wc.OpenReadAsync(new Uri("...")); ...private void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e){ if (e.Error == null) { using (StreamReader reader = new StreamReader(e.Result)) { string rss = reader.ReadToEnd(); // TODO: Parse the feed } }}
![Page 9: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/9.jpg)
demoWebClient
![Page 10: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/10.jpg)
• Delegate-based HTTP networking API– Asynchronous operation only
• Generally used to call untyped HTTP services– e.g., REST services
• Completion methods called on background threads from CLR thread pool– Use Dispatcher.BeginInvoke to update UI
HttpWebRequest
![Page 11: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/11.jpg)
Calling a REST Service (GET)
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create (new Uri("http://contoso.com/weather/98052"));request.BeginGetResponse (new AsyncCallback(OnGetResponseCompleted), request); ...private void OnGetResponseCompleted(IAsyncResult ar){ HttpWebRequest request = (HttpWebRequest)ar.AsyncState; HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(ar);
using (StreamReader reader = new StreamReader(response.GetResponseStream())) { string result = reader.ReadToEnd(); ... }}
![Page 12: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/12.jpg)
Calling a REST Service (POST)
HttpWebRequest request = (HttpWebRequest) HttpWebRequest.Create (new Uri("http://contoso.com/weather"));request.Method = "POST";request.ContentType = "application/x-www-form-urlencoded";request.BeginGetRequestStream(new AsyncCallback (OnGetRequestStreamCompleted), request); ...private void OnGetRequestStreamCompleted(IAsyncResult ar){ HttpWebRequest request = (HttpWebRequest)ar.AsyncState; using (StreamWriter writer = new StreamWriter(request.EndGetRequestStream(ar))) { writer.Write("98052"); // Write input into body of request } request.BeginGetResponse(new AsyncCallback(OnGetResponseCompleted), request);} ...private void OnGetResponseCompleted(IAsyncResult ar) { ... }
![Page 13: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/13.jpg)
demoHttpWebRequest
![Page 14: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/14.jpg)
• Callable through WCF Web service proxies– Use Visual Studio's "Add Service Reference"
command to generate proxies• Selected WCF bindings supported
– BasicHttpBinding (WS-I Basic Profile 1.0)– Custom HTTP binding with binary message
encoding– No PollingDuplexHttpBinding or NetTcpBinding
• Asynchronous operation only
ASMX and WCF Services
![Page 15: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/15.jpg)
• Use "Add New Item" -> "Silverlight-Enabled WCF Service" command in Visual Studio
Creating a WCF Service
![Page 16: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/16.jpg)
Calling a WCF Service
ZipCodeServiceClient proxy = new ZipCodeServiceClient();proxy.GetCityAndStateFromZipCodeCompleted += new EventHandler<GetCityAndStateFromZipCodeCompletedEventArgs> (GetCityAndStateFromZipCodeCompleted);proxy.GetCityAndStateFromZipCodeAsync("98052"); ...private void GetCityAndStateFromZipCodeCompleted(object sender, GetCityAndStateFromZipCodeCompletedEventArgs e){ if (e.Error == null) { Place place = e.Result; // Method returns Place object string city = place.City; string state = place.State; ... }}
![Page 17: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/17.jpg)
demoWCF Services
![Page 18: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/18.jpg)
• Asynchronous notifications delivered to phones
• Utilize Microsoft Push Notification Service (PNS)– Hosted in Azure; massively scalable and reliable– Battery- and bandwidth-efficient alternative to
polling• Three types of notifications
– Raw notifications– Toast notifications– Tile notifications
• Toast and tile notifications work if app isn't running
Push Notifications
![Page 19: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/19.jpg)
How Push Notifications Work
Microsoft PushNotification Service
YourWeb Service
Count
3
4
Phone transmits URI to Web service
Service calls PNSusing transmitted URI
5
12
PNS sends notification to phone
PNS returns URI
Phone app requests URI from PNS
![Page 20: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/20.jpg)
• Delivered only when app is active– If app is inactive, call to PNS returns HTTP 200
OK with notification status == "Suppressed"• Payload can be text or binary data
– 1K maximum payload size
Raw Notifications
![Page 21: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/21.jpg)
Raw Notification Wire Format
POST uri HTTP/1.1X-NotificationClass: intervalHost: uriContent-Type: application/*; charset=UTF-8Content-Length: length
payload
![Page 22: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/22.jpg)
Sending a Raw Notification
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;request.Method = WebRequestMethods.Http.Post;
request.Headers.Add("X-NotificationClass", "3"); // Send immediately
using (Stream stream = request.GetRequestStream()){ byte[] payload = Encoding.UTF8.GetBytes(message); stream.Write(payload, 0, payload.Length);}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
![Page 23: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/23.jpg)
• Delivered even when application is inactive– Displayed in toast window at top of screen– Clicking toast window activates application
• Also delivered when application is active– Not automatically displayed– App decides what to do
Toast Notifications
![Page 24: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/24.jpg)
Toast Notification Wire Format
POST uri HTTP/1.1X-NotificationClass: intervalX-WindowsPhone-Target: toastHost: uriContent-Type: application/*; charset=UTF-8Content-Length: length
<?xml version="1.0" encoding="utf-8"?><wp:Notification xmlns:wp="WPNotification"> <wp:Toast> <wp:Text1>MessageCaption</wp:Text1> <wp:Text2>MessageText</wp:Text2> </wp:Toast></wp:Notification>
![Page 25: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/25.jpg)
Sending a Toast Notification
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;request.Method = WebRequestMethods.Http.Post;
request.ContentType = "text/xml";request.Headers["X-WindowsPhone-Target"] = "toast";request.Headers.Add("X-NotificationClass", "2"); // Send immediately
using (Stream stream = request.GetRequestStream()){ byte[] payload = Encoding.UTF8.GetBytes (String.Format(_template, caption, message)); request.ContentLength = payload.Length; stream.Write(payload, 0, payload.Length);}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
![Page 26: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/26.jpg)
• Update tiles pinned on start screen ("live tiles")– Change tile background image
• Local or remote images• Max size 80K; must load in under 15 seconds
– Change count displayed in tile's upper-right corner
– Change title displayed along tile's bottom border
Tile Notifications
Title
Count
![Page 27: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/27.jpg)
Tile Notification Wire Format
POST uri HTTP/1.1X-NotificationClass: intervalX-WindowsPhone-Target: tileHost: uriContent-Type: application/*; charset=UTF-8Content-Length: length
<?xml version="1.0" encoding="utf-8"?><wp:Notification xmlns:wp="WPNotification"> <wp:Tile> <wp:BackgroundImage>BackgroundImageUri</wp:BackgroundImage> <wp:Count>Count</wp:Count> <wp:Title>Title</wp:Title> </wp:Tile> </wp:Notification>
![Page 28: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/28.jpg)
Sending a Tile Notification
HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;request.Method = WebRequestMethods.Http.Post;
request.ContentType = "text/xml";request.Headers["X-WindowsPhone-Target"] = "token";request.Headers.Add("X-NotificationClass", "1"); // Send immediately
using (Stream stream = request.GetRequestStream()){ byte[] payload = Encoding.UTF8.GetBytes (String.Format(_template, imageuri, count, title)) request.ContentLength = payload.Length; stream.Write(payload, 0, payload.Length);}
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
![Page 29: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/29.jpg)
• Calls to PNS return important information in HTTP status codes and custom response headers– X-NotificationStatus– X-SubscriptionStatus– X-DeviceConnectionStatus
• Certain response codes must not be ignored– Subscription may be expired– Subscription may require server-side throttling
• Response codes documented at http://msdn.microsoft.com/en-us/library/ff941100(v=vs.92).aspx
PNS Response Codes
![Page 30: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/30.jpg)
Sample Response Codes
HTTP Status
Notification Status
Subscription Status
Device StatusComments
200 Received Active Connected Notification was accepted
200 Received ActiveTempDisconnected
Notification was accepted, but device is disconnected
200 QueueFull Active Any valueNotification queue is full; try again later
200Suppressed
Active Any valueNotification could not be delivered because application is not active
404 Any value Any value ExpiredSubscription has expired and should be deleted; do not resend
406 Any value Any value Any valuePer-day quota has been reached; can try to resend once per hour
412 Any value Any value Any valueDevice is inactive; can try to resend once per hour, but with penalties
503 Any value Any value Any value PNS is unavailable
![Page 31: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/31.jpg)
Handling Response Codes
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
int status = (int)response.StatusCode;
string xsubscription = null;if (response.Headers["X-SubscriptionStatus"] != null) xsubscription = response.Headers["X-SubscriptionStatus"].ToString();
if ((xsubscription != null && xsubscription == "Expired") || status == 404 || status == 406 || status == 412){ // Delete the subscription RemoveSubscription(uri);}
![Page 32: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/32.jpg)
• Class used to connect phone apps to PNS
HttpNotificationChannel
Method Description
BindToShellTile Binds channel to tile notifications
BindToShellToast Binds channel to toast notifications
Close Close an open channel
Find Returns an existing channel if that channel exists
Open Opens a channel
UnbindToShellTile Unbinds channel to tile notifications
UnbindToShellToast
Unbinds channel to toast notifications
![Page 33: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/33.jpg)
Opening a Channel
channel = HttpNotificationChannel.Find("MyChannel");
if (channel == null) // Create a new channel{ channel = new HttpNotificationChannel("MyChannel"); RegisterChannelEventHandlers(channel); channel.Open(); // Generates ChannelUriUpdated event}else // Configure an existing channel{ RegisterChannelEventHandlers(channel); BindChannel(channel);
// TODO: Send the URI to the Web service}
![Page 34: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/34.jpg)
Binding to Notifications
// Configure the channel to report toast notificationsif (!channel.IsShellToastBound) channel.BindToShellToast();
// Configure the channel to support tile notificationsif (!channel.IsShellTileBound) channel.BindToShellTile();
![Page 35: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/35.jpg)
Handling Raw Notifications
channel.HttpNotificationReceived += OnRawNotificationReceived; . . .void OnHttpNotificationReceived(object sender, HttpNotificationEventArgs e){ // Transfer to UI thread if updating the UI Dispatcher.BeginInvoke(() => { // Payload in e.Notification.Body });}
![Page 36: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/36.jpg)
Handling Toast Notifications
channel.ShellToastNotificationReceived += OnToastReceived; ...void OnToastReceived(object sender, NotificationEventArgs e){ // Transfer to UI thread if updating the UI Dispatcher.BeginInvoke(() => { string caption = String.Empty; if (e.Collection.ContainsKey("wp:Text1")) caption = e.Collection["wp:Text1"];
string message = String.Empty; if (e.Collection.ContainsKey("wp:Text2")) message = e.Collection["wp:Text2"];
... });}
![Page 37: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/37.jpg)
Handling Tile Notifications
This space intentionally left blank
![Page 38: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/38.jpg)
• Limit of one open channel per app• Limit of 15 open channels per device
– No way to know ahead of time how many are open
– HttpNotificationChannel.Open throws InvalidOperationException when limit is exceeded
• Limit of 500 notifications per day per channel– Limit waived for authenticated Web services
• Apps that use push notifications must comply with WP7 Application Certification Requirements
Constraints and Limitations
![Page 39: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/39.jpg)
demoPush Notifications
![Page 40: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/40.jpg)
• ShellTileSchedule class permits tiles to be updated periodically by downloading them from a server– Does not count against push notification limit– Frequency cannot exceed one update per hour
• Options are hourly, daily, weekly, monthly– Max image size 80K; must load in < 15 seconds
• Updates suspended when screen is locked or off– Updates fire immediately when screen unlocks
Tile Scheduling
![Page 41: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/41.jpg)
Scheduling Hourly Updates
ShellTileSchedule sts = new ShellTileSchedule();
sts.Interval = UpdateInterval.EveryHour;sts.MaxUpdateCount = 0; // Run indefinitelysts.Recurrence = UpdateRecurrence.Interval;sts.RemoteImageUri = new Uri(@"http://www.wintellect.com/tiles/hourlyimage.png");
sts.Start();
![Page 42: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/42.jpg)
Performing a One-Time UpdatexShellTileSchedule sts = new ShellTileSchedule();
sts.Recurrence = UpdateRecurrence.OneTime;sts.StartTime = DateTime.Now;sts.RemoteImageUri = new Uri(@"http://www.wintellect.com/tiles/tile.png");
sts.Start();
![Page 43: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/43.jpg)
Detecting Connectivity Status
if (NetworkInterface.GetIsNetworkAvailable()){ // App is connected}else{ // App is not connected}
![Page 44: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/44.jpg)
Detecting Status Changes
NetworkChange.NetworkAddressChanged += OnNetworkAddressChanged; . . .void OnNetworkAddressChanged(object sender, EventArgs e){ if (NetworkInterface.GetIsNetworkAvailable()) { // App is connected } else { // App is not connected }}
![Page 45: Charles Petzold Networking](https://reader031.vdocument.in/reader031/viewer/2022020105/55178cd85503460e6e8b580b/html5/thumbnails/45.jpg)
Charles Petzoldwww.charlespetzold.com
Questions?