Zero Configuration Networking: The Definitive Guide
7.1. Asynchronous Programming Model
Before diving into the details of Zeroconf programming, there's one important high-level issue to understandDNS-SD operations are asynchronous. That means that when you initiate some DNS-SD operation, the results of that operation may happen immediately, half a second later, a minute later, or even days later. Consider one real-world example, iTunes. When you run iTunes, it browses for other music sources on the local network. If you launch iTunes at home, there may be no other music sources, so nothing appears. A few days later, a friend may come to visit with a laptop offering shared iTunes music. Your friend connects his laptop to your network and, instantly, he appears in your iTunes list. That browse operation initiated by iTunes several days ago has just yielded its first result! To create a good user experience, it's essential to understand and embrace this asynchronous programming philosophy. We've all seen, at some time or another, bad user interfaces where you get to watch some cute animation for 15 seconds while the computer "searches" the network, and then it stops "searching" and shows you what it's found. If the thing you're looking for isn't there, you have to try to fix what's wrong, then click some refresh button and watch the cute animation for another 15 seconds before you find out whether it worked this time. For the programmer, there's no right answer for a fixed search time . If you set the search time too short, you risk giving up before all devices have responded, particularly on slow or busy networks. If you set the search time too long, you frustrate the user. A 15-second wait may be tolerable just once, but when the user is trying to troubleshoot a problem and she has to suffer that 15-second wait over and over and over, she gets very frustrated. DNS-SD solves this dilemma by simply not having a fixed search time. DNS-SD operations run for an indeterminate length of time, until you stop them. Results are delivered as they come, not all at the end after some fixed timeout. You can expect the first browsing results to show up in as little as a few milliseconds. Slower devices may take a second or two to respond. Devices not yet connected to the network will, of course, only show up once they are connected, which could be hours, days, or weeks later. Don't be tempted to make a Zeroconf application that starts a browse operation, lets it run for some fixed time, and then stops it and presents the results to the user. Zeroconf applications don't work this way, and yours will look crude and amateurish if you make this mistake. In particular, you should never have a Refresh button in Zeroconf UIas long as a DNS-SD browsing list is on the screen, it should be fresh all the time, so the user never needs to refresh it. DNS-SD uses a range of techniques to make long-lived operations efficient on the network. Writing code that once a minute does a DNS-SD browse for five seconds to see what's there and then stops it would actually be a lot less efficient on the network than just leaving a browse operation running continuously. To support this asynchronous programming philosophy, DNS-SD needs a way to deliver these asynchronous events to your application as they happen. There is no one universal mechanism for delivering asynchronous events that's common among all programming languages, programming models, and operating systems. Some programming models are built around a single main event loop that receives an event notification, handles it, receives another event notification, handles it, and so on. Other programmers prefer to write multithreaded code, where each thread blocks and waits for a particular event of interest. Still other models use concepts like signal handlers or interrupt routines, where, when an event happens, the main thread is interrupted and suspended wherever it happens to be, the event handler routine is run, and then, afterward, control returns to the main thread. Rather than try to dictate a particular programming model to use, the DNS-SD C API instead provides the necessary primitives so you can integrate its event delivery into whatever event-handling model you've chosen for your program. If you're using a main event loop, there are two things you need to do: you need to tell your main event loop to pay attention to DNS-SD event sources and, when one of those events happens, you need to ask DNS-SD what to do about it. In this chapter, you'll see how to use DNS-SD C API with the various commonly used main event loop models: the Unix select( ) call, the Cocoa RunLoop, the Core Foundation CFRunLoop, and the Microsoft Windows GetMessage( ) Message Loop. You'll also see how to use DNS-SD C API by creating a separate independent thread for each active DNS-SD operation, if that's your preferred way of working. We'll start by showing how to do each of the common DNS-SD operations using a Unix select( ) loop and then, later in the chapter, cover just the differences when using other event-handling models. |
Категории