Bonjour is a technology that makes the discovery of services very easy. Despite its power and ease of use, it doesn’t receive much attention in the Cocoa community. Bonjour works very well with the CocoaAsyncSocket library, an open-source library that provides an Objective-C interface for working with sockets on iOS and OS X. In this series, I will introduce you to Bonjour and the CocoaAsyncSocket library by creating a simple, networked game. Along the way, I will initiate you into the world of networking by discussing the TCP and UDP protocols as well as sockets, streams, and ports!
In this series, we will create a simple networked game. Our primary focus will be the networking aspect of the game. I will show you how to connect two devices using Bonjour and the powerful CocoaAsyncSocket library. The game that we will create allows two people on the same network to challenge each other. The game itself won’t be very advanced, so don’t expect a graphically rich FPS.
In this series, I will not talk about the infrastructure that enables networked applications to communicate with one another. Instead, I will focus on the protocols and technologies that form the foundation of networked applications. A basic understanding of the TCP and UDP protocols, sockets, and streams is invaluable for any developer, particularly those who plan on creating applications that rely on network connectivity. Even if you don’t intend to use Bonjour, I highly recommend reading the rest of this article to get a better understanding of networking.
In this article, I will zoom in on several key components of networked applications. It will help you understand how Bonjour works, what Bonjour is (and isn’t), and it will also make working with the CocoaAsyncSocket library much easier.
Keep in mind that Bonjour isn’t required to develop a networked application. Most Unix-based operating systems, such as iOS and OS X, use BSD sockets as their fundamental network programming interface. On iOS and OS X, the BSD Socket library is readily available. Working with the BSD Socket library, however, is not for the faint of heart and requires an in-depth knowledge of socket programming and the C language. On iOS and OS X, you can also make use of the low-level CFNetwork framework, which is a direct extension to BSD sockets. Apple designed the CFNetwork framework to make networking easier by avoiding direct interaction with BSD sockets. One of the most important advantages of CFNetwork is its built-in support for run-loop integration. CFNetwork is part of the Core Foundation framework and written in C.
A surprising number of iOS and OS X developers are so used to the Objective-C syntax that they shy away from libraries and frameworks written in C. If you are one of those developers, then the CFNetwork framework may seem daunting. However, there is a solution for this, and its name is CocoaAsyncSocket. The CocoaAsyncSocket library makes interacting with sockets easier, and it also provides an elegant Objective-C interface. The current version of the CocoaAsyncSocket library integrates neatly with Grand Central Dispatch (GCD) which makes asynchronous programming a breeze.
Let’s start by taking a closer look at the basics of networking. Without a good grasp of sockets, ports, and streams, even Bonjour and the CocoaAsyncSocket library won’t be of much use to you!
Under The Hood
Networking is not easy and this is something that won’t change anytime soon. Even though the infrastructure that gives us access to the Internet has changed dramatically during the past several decades, the underlying technologies and protocols have changed very little. The reason is that the services we use daily rely heavily on the underlying logical protocols and much less on the physical infrastructure. In the nineties, most of us browsed the web through a dial-up connection. Nowadays, the majority of people have access to a fast broadband connection, and in the past few years a significant portion of the web has begun to be consumed through mobile devices. In other words, the infrastructure has changed dramatically, but the logical protocols necessary for routing traffic and interacting with applications haven’t changed as dramatically.
Never Change a Winning Team
Another reason that the fundamental technologies and protocols that we use to transmit data on the Internet haven’t changed much is because they have proven reliable, performant, and robust. Those technologies and protocols are well tested and they have proven themselves countless times over the past few decades.
Sockets, Streams, and Ports
As a developer, you have probably heard of sockets, ports, addresses, and the like. If you are not familiar with these terms, then you are in for a treat as I will introduce you to the wonders of sockets, ports, streams, and protocols. To get a basic understanding of networking, it is key that you know the bascis of networking and that includes sockets and its friends.
Local and Remote Sockets
A network connection operates through sockets. A socket is one end of a communication channel between two processes that want to talk to each other. As you might have guessed, a network connection (or interprocess communication channel) has two sockets, one for each end of the channel. A network connection is established by one socket making a connection with another socket, the listening socket, which is listening for incoming connections.
The difference between a local and remote socket is merely semantic. From the perspective of a socket, the socket is the local socket and the socket it is connected to is the remote socket. That makes sense. Right?
While a socket is used to send and receive data, a stream can either read data or write data. This means hat in most cases each socket has two streams, one for reading and one for writing. Even though streams are an important aspect of socket programming, we won’t work with streams directly as streams are managed for us by the CocoaAsyncSocket library.
Establishing a Network Connection
Each socket has an address that consists of the host address and a port number. Both parts are essential to establish a connection between two sockets. To keep things simple, the host address is usually the IP (Internet Protocol) address of the machine while the port number uniquely identifies the socket on the machine. Compare this concept with an apartment complex. The building has an address so people know where to find it. Each apartment in the building has a unique number so visitors of the complex can find the apartment they are looking for.
Transmitting data over the Internet is a complex process, and it has resulted in the creation of two robust protocols for uniformly sending and receiving data: TCP (Transmission Control Protocol) and UDP (User Datagram Protocol). Both protocols are transport layer protocols and part of the Internet Protocol (IP) suite.
I am sure that TCP and UDP ring a bell with most of you. There are several key differences between both protocols and it is important to understand those differences. In this series, we will focus on the TCP protocol. A TCP connection manages a stream of data from one endpoint to another.
The key differences between TCP anad UDP are speed and how they cope with network reliability. If you want to make sure that what is sent through one end of the connection comes out at the other end, then TCP is your friend. TCP is slower than UDP, but it has a good reason for being slower. Without going into too much detail, it is important to know that TCP establishes and terminates a connection with a handshake to identify both ends of the connection. It also makes sure that each packet that is sent through the channel arrives at the other end. In addition, TCP ensures that the order of the packets is respected.
One of the reasons that UDP is faster than TCP is because it doesn’t require a handshake when establishing and terminating a connection. In addition, the UDP protocol doesn’t care if a packet arrives and it also doesn’t care about the order in which packets arrive. If a packet is dropped along the way, the UDP protocol does not try to resend it as it is not even aware of the packet being dropped. The main concern of UDP is that data is sent through the communication channel as fast as possible.
I am sure that you are beginning to see that TCP and UDP are very different protocols and that each protocol serves a different purpose. UDP, for example, is ideal for streaming live audio and video. Speed is essential in these situations. It doesn’t matter if a packet is dropped along the way. If a dropped packet would be resent, it would arrive late and for live streaming it would no longer be relevant. Online multiplayer games also benefit from UDP. The speed of UDP is more important than its reliability. Packets that arrive too late are no longer relevant and that is the fundamental idea behind UDP – speed over reliability.
TCP, on the other hand, is all about reliability. It is used for email and browsing the web. It is a bit slower, but it will do its very best to make sure that you receive what you asked for. The TCP protocol is very robust and supports resending dropped packets and it also respects the order in which packets are sent. Even though we will be using the TCP protocol in this series, keep in mind that the CocoaAsyncSocket library also supports the UDP protocol.
Client and Server
In terms of networking, there is one more concept you need to understand: the client-server model. In every communication, there is a client and a server. Compare this model with two people people making a phone call. Steven wants to make a phone call to Lucy. There are three fundamental requirements for this to work.
- The first requirement is that Steven knows about Lucy and he needs to know Lucy’s telephone number. The same is true for a client trying to connect to a server. The client needs to know about the existence of the server and it needs to know the server’s address.
- The opposite, however, is not true. Lucy does not need to know anything about Steven for Steven to call Lucy. In other words, a server does not need to know about the existence of a client for the client to connect to the server.
- Once the connection is established, Steven can talk to Lucy and Lucy can talk to Steven. When a client is connected to a server, the client can send data to the server and the server can send data to the client.
This concept of a client and a server will become important when we look at Bonjour in practice in the next article of this series. Let’s conclude this tutorial by taking a brief look at Bonjour.
Where Does Bonjour Fit In?
What is Bonjour and how does it fit in our story? Bonjour is a technology created by Apple and based on Zeroconf. Its primary goal is to make the discovery of services easy. Chances are that you have used Bonjour numerous times without even knowing it. Have you ever used a printer on your local network? Didn’t it strike you that it took almost no effort to use the printer even though it wasn’t physically connected to your computer? Apple’s Remote iOS application also makes use of Bonjour, and so do a lot of other iOS and OS X applications.
Even though Bonjour is a great technology, keep in mind that it doesn’t take care of sending or receiving data. What Bonjour does very well is publishing and discovering services that are on the same local network. In the next article, we will take a closer look at Bonjour’s API’s and we will start building the client-server model that we discussed in this article.
With this introductory tutorial, you should have a basic understanding of networking, the various components involved, and the role of each component. In the remaining parts of this series, we will revisit and use some of these components so it is key that you understand what we covered in this article. In the next article, I will talk more about the client-server model by showing you how to connect two devices using Bonjour and the CocoaAsyncSocket library.