Creating a minimalist web server running inside your app on an iPhone offers some interesting scenarios for sharing data on your local network. You can use this to serve up html, but I thought it would be interesting to have it serve up a Silverlight app. Since Silverlight apps are packaged in zip files (with a different extension, .xap) they make for a clean deployment in an iphone app scenario. You can create the server in your app using Systems.Net.Sockets. For example you can create a class that uses TcpListener to accept incoming traffic and then use TcpClient to get the network stream for reading and writing. Once you have this you can parse the incoming requests in accordance to whatever protocol (or subset thereof) you want to support and then write your response back with whatever content you want served up to the caller. In this case, I’m looking for http traffic and based upon the uri in the request, serving up just the few things needed to get the silvelight app, stored in the iphone app, to the client browser.
The first thing you need to do is get an address for the TcpListener to listen on. Note this is a bit different between the simulator and the device as the later does not include the “.local” suffix when resolving the host name, so you’ll need to add it.
#if (SIM) IPAddress localAddr = IPAddress.Parse ("127.0.0.1"); int port = 0; #else string hostName = System.Net.Dns.GetHostName () + ".local"; int port = 0; IPHostEntry hostEntry = Dns.GetHostByName (hostName); IPAddress localAddr = hostEntry.AddressList[0]; #endif
Once you have the address you can use it to create a TcpListener and as requests come in, parse them to serve up the necessary responses for Silverlight, which are the hosting html page, the Silverlight.js file and the .xap file itself. For a Silverlight app that makes no additional network calls internally, once it’s at the client browser, no additional server support will be needed. If you want additonal calls supported for images, other files or whatever else you can think of, you can implement them in the server in a similar fashion to that used in serving up the xap.
... while (true) { RaiseLogEntryEntered ("mtServer is alive and listening"); TcpClient tcpClient = tcpListener.AcceptTcpClient (); using (NetworkStream netStream = tcpClient.GetStream ()) { string request = ReadRequest (netStream); string uri = ParseGetUri (request); if(uri.EndsWith(".js")) { SendSilverlightJavascriptResponse(netStream); } else if(uri.EndsWith(".xap")) { SendSilverlightXAPResponse(netStream); } else //default everything else to the hosting html page (could get more granular here if we want) { SendSilverlightHostPageResponse(netStream); } tcpClient.Close (); } ...
The SendXYZ methods are just wrappers on a single call to send a response to the client browser:
void SendResponse(NetworkStream netStream, string contentType, string resourcePath) { byte[] resource = File.ReadAllBytes(resourcePath); string responseHeaders = String.Format ("HTTP/1.1 200 OK\r\nContent-Length: {0}\r\nContent-Type: {1}\r\n\r\n", resource.Length, contentType); byte[] responseHeadersEncoded = Encoding.UTF8.GetBytes (responseHeaders); netStream.Write (responseHeadersEncoded, 0, responseHeadersEncoded.Length); RaiseLogEntryEntered (String.Format ("Response:\r\n{0}", responseHeaders)); netStream.Write(resource, 0, resource.Length); }
In the iPhone app I created a view with a UILabel to show the address that the app is listening on and a UITextView to display the raw traffic from the http server.
Here are screenshots of the iPhone app running on the device and the Silverlight app served up to Safari on my Mac:



Hello Mike!
Any reason why you did not use the built-in HTTP server HttpListener?
miguel.
Good point, it should use HttpListener.
where can i get TCPClient and TCPListener
Got it.. System.Net.Sockets 🙂