Thursday, 12 November 2009

Apple iPhone Tech Talk London 2009: Networking: From Sockets to GameKit

Paul Danbold danbold@apple.com — Evangelist

This was another really fast presentation with loads of detail. I look forward to grabbing the presentation from the iPhone dev site.

  • don’t want to use CFSocket or BSD Socket
    • don’t let you bring up wireless, or involve security
  • service discovery:
    • NSNetServices, CFNetServices, dns-sd, BSD Sockets
    • dns-sd is Bonjour or Zeroconf

URL Loading system

  • NSURLRequest, NSURLConnection & about 10 other classes (also mutable ones)
  • there’s sample code for validating URLs
  • recommend to use asynchronous API style:
    • use delegate mechanism — calls connection:didReceiveResponse:
  • also connection:didReceiveAuthenticationChallenge:
  • finally connectionDidFinishLoading:
  • default behaviours should work fine

Local area networking — service discovery

  • kick off NSNetServiceBrowser in asynchronous mode, w/delegation
  • browser searchForServicesOfType:inDomain:
    • e.g. type _http._tcp in domain local. — don’t go beyond any routers
    • can look for your own types too such as _foo._tcp
  • then get myServiceBrowser:didFindService:moreComing:
  • call NSNetworkService getInputStream:outputStream to resolve
    • this takes time (many seconds)
    • wait for the user to choose before resolving
    • and let the user decide when to cancel
    • resolveWithTimeout:0.0
  • must release input & output stream objects returned by NSNetService
    • bug in Apple’s code — doesn’t obey normal Cocoa behaviour

OutputStream & InputStream

  • NSStreamEventHasSpaceAvailable is probably the interesting one
  • though you want to handle the errors too…

advertising & publishing

  • advertise service with NSNetService initWithDomain:type:name:port
    • domain can be empty — means local
    • name can be blank too — will use device’s iTunes name
  • then call publish on service

stop when you’re done

  • browsing is fairly lightweight on the network, but you should stop anyway
  • the same goes for publishing, when you’ve got all your connected clients

register types & ports

game kit — peer to peer

  • 3.1 adds WiFi support as well as Bluetooth
  • GKSession initWithSessionID:displayName:sessionMode
    • session ID is your Bonjour service type — how you advertise yourself
    • again, can leave displayName as nil for iTunes name
    • sessionMode can be peer to peer (1 to 1) or client/server (multiple clients)
  • can’t physically go over 10-20 clients with Bluetooth
    • 3.1 and later is a lot better, but still no more than 3-4 clients
    • Bluetooth also has low bandwidth
  • set up delegate and set available to YES
  • check other peers with peersWithConnectionState:
    • can be available, already connected, in the process of getting connected
  • connectToPeer:withTimeout:
    • generally set timeout to zero to let user cancel if they want
  • actual connection made with session:didReceiveConnectionRequestFromPeer: and acceptConnectionFromPeer:error:
  • must monitor the network using session:peer:didChangeState:
    • other players can drop out, so you’d have to tear down your session
  • send data with sendDataToAllPeers:withDataMode:error: and sendDataToPeers:...
    • can choose unreliable (UDP) or reliable (TCP) data modes
    • as always TCP imposes a performance cost so use sparingly
  • receive data with setDataReceiveHandler:withContext: and receiveData:fromPeer:inSession:context:
  • always check for errors — buffers fill up on low bandwidth networks
    • check it by using a slow network
  • when you’re finished, tear down with disconnectFromAllPeers:
  • there’s a GKPeerPickerController for setting up Bluetooth peers
    • doesn’t work for client/server or WiFi
  • the only way to find out if Bluetooth is turned on is to use the GKPeerPickerController (it uses private APIs…)
  • all data sent & received is NSData-wrapped — design your packaging for network efficiency first and coding efficiency second

Voice chat

  • GKVoiceChatClient and ~Service
  • sets up socket interface
  • handles microphone, echo suppression, etc

network challenges

scoped routing and reachability

  • iphone 3.0 and later provides scoped routing
    • keeps both cellular and wifi up at the same time — so cellular connections keep going when you enter a wifi hotspot
    • but this puts a toll on the battery, so you should behave and check for networking changes
  • use SystemConfiguration APIs to monitor network state
    • Am I on the network and what kind of network is it?
    • cannot tell you that packets will arrive…
    • if network changes, finish what you’re doing, close connection and start a new one
  • use SCNetworkReachabilityRef and check for flags
    • but again use callback APIs since the calls take about 30 seconds
  • no point using this to pre-flight as things may change
    • just use to monitor
  • can set UIRequiresPersistentWiFi key
    • keeps WiFi live while your app is live
    • shows up UI elements automatically (like offering to turn off Airplane mode)
    • but if the device sleeps, you still lose your WiFi connection

battery use

  • listening is cheap, transmitting is expensive
  • 3GS sending leaves the antenna in high powered state for 5 seconds
    • so don’t send every 5 seconds — it will leave it in high power continuously
  • compress data, send large chunks
  • tear down connections when reachability changes

other tips

  • try to use the cache as much as possible
  • try to resume downloads rather than restart
  • use pipelining if poss.
    • ask for lots of things at once and be careful about return order
    • some web proxies and apache configs just break pipelining
  • also use multiple connections
  • but different network conditions and different servers require different tuning
  • test in areas where you know the network is flaky!
  • use a packet analyzer — see QA1176
  • try to isolate the user from network problems
    • often there’s a transient glitch — try again before alerting the user
  • see also Technote TN2152
  • look for developer forum postings by eskimo1 :-)

there’s some new sample code available:

  • SimpleNetworkStreams
  • SimpleURLConnection
  • SimpleFTPSample
  • Reachability — there’s a new version! The old version had bad code :-)
  • BonjourWeb
  • WiTap — peer to peer, but doesn’t use GameKit
  • GKTank
  • GKRocket — work in progress, with voice chat too

1 comment:

Alan Serhan said...

Hi Adam!
Thanks for the briefs. But how can one create a custom UI instead of the normal popup "available bluetooth devices" screen?

Best regards

Alan Serhan