Chapter 16. Connecting with the Outside World

We have covered a lot in the previous two chapters. In fact, you should now know enough to build a wide range of applications that utilize networking APIs to connect to each other. But so far, we have been talking about games that can be played only by people whose iPhones and iPod touches are connected to the same wireless networks, or that are located within several feet of each other, reachable by Bluetooth. In some cases, you can dismiss these limitations as not very significant—after all, having an interactive gaming session with other human beings that share the same physical space could be classified as "the ultimate social experience." However, as the world is getting more and more connected, there remain fewer excuses that justify leaving your players around the world disconnected from one another.

If you agree with the basic premise that "everything and everyone want to be connected," then you'll want to know what it takes to bring your already-networked games online, or add some social elements to your still-solitary applications. This chapter provides a brief introduction to using the Internet to enhance your users' gaming experience.

Challenges

To make this exercise less abstract, let's examine what would it take to add online game play capabilities to the games that we created in Chapters 14 and 15: GKPong and TwentyFour. How can the iPhone SDK help us here? And is there anything that the SDK can't do for us in this regard? What are some of the challenges that we will be facing in our quest to bring these games online?

Au Revoir, Bonjour!

The first casualty of such a transition is Bonjour—the technology that we learned to love and respect, and the one that makes it easy for us to find opponents and discover game servers. The reason is quite simple: Currently, due to the way Bonjour is designed, developers can't use it outside local networks. Even though there are some ways to make Bonjour operate over the Internet, as we've seen Apple do with MobileMe and Back to My Mac, such work-arounds seem too complicated to be practical for game developers.

Although the situation might change in the future, as of right now, Bonjour is pretty much useless for online multiplayer games. For a game like TwentyFour, this means replacing the mechanism that allows us to look for servers to connect to.

Note

If you need your game to have both a local and online options, you will still want to use NSNetServices for the local part, in addition to whatever needs to be done for online game play to work.

No GameKit Peer-to-Peer for You!

Losing Bonjour also means losing the peer-to-peer capabilities of GameKit, since the latter heavily relies on the former to discover peers and figure out how to establish sessions

Given that all of the networking aspects of GKPong are based on this functionality, it means that we would need to rewrite quite a bit of that game.

Server, interrupted

Imagine playing a game of TwentyFour with a bunch of friends. You launch the app on your iPhone, tap "Start new game," and tell everyone to join in. You are in the middle of a round, desperately trying to figure out the answer. Suddenly, your iPhone starts ringing—it's your mom calling. As soon as you take the call, your game is terminated. What happens to all of the players? They get disconnected and kicked back out into the lobby, of course. Now, this would be unfortunate. But, given that all your friends are in the same room—and perfectly capable of arranging another game while you are on the phone—it's not such a big issue.

Now suppose that this game is being played online, and you have several people from around the world connected to the server running on your iPhone (isn't technology wonderful?). In that case, disconnecting all of them at once would make the players feel a lot worse, since it would happen without a warning, and you wouldn't be able to easily tell them, "It's my mom. I'll be right back."

What does this tell us? In order to be usable online, a game server, like the one built into TwentyFour, needs to be a lot more reliable and available than what we can get out of an app running on a device with a limited battery life, and subject to the availability of 3G or a Wi-Fi signal.

For a game like GKPong, this is not such a big issue. Whenever there are only two players, if one of them gets distracted, the whole game is effectively over, even if the game server remains available. The other opponent simply doesn't have anyone to play against. But this doesn't mean that we can get away with not introducing a centralized server in this case. Remember that we no longer have Bonjour to play matchmaker for us. We'll need to replace it with some sort of a game server whose "contact information" is known to both clients beforehand.

Lag

Slow communication is one of the more serious issues facing online multiplayer game developers, and it's the one that you cannot really remove; you can only code around it. Simply stated, it takes time for packets to travel over the Internet. How much time they will spend in transit depends on several variables, such as connection speed on both the sender's and receiver's end, and distance between the two peers. A more technical term to describe the amount of time that it takes a message to get from one end to another is latency.

It takes a typical GKPong message only a few milliseconds to travel from one iPhone to another via Bluetooth. But as soon as you start sending data over the Internet, expect it to take at least ten times as long on a broadband connection, and even longer over a cellular data connection. Whenever high latency starts negatively impacting gaming experience by making game play feel slow or unresponsive, players start complaining of "lag."

Real-time games like GKPong usually suffer a lot more from lag issues than games like TwentyFour, where other players don't expect to see results of their actions as soon as they happen. It's not a problem if your answer arrives a second later—it will still be counted. In GKPong, however, due to the way we chose to implement it, if the gkMessageBallBounced message spends any significant time traveling from my iPod touch to yours, you will start seeing the ball jittering and going out of bounds before bouncing back.

If you are interested in learning more about how to go about solving problems related to high latency in online games, look for materials related to "lag compensation in multiplayer games."

Tip

One crude way to simulate lag in your games is to schedule messages to be sent out in the future instead of immediately whenever you need to communicate something. Since you don't want to make your overall application sluggish by "sleeping," use NSObject's performSelector:withObject:afterDelay: to postpone execution of methods responsible for sending out messages.

It's All Greek to Me...

Remember how we used NSKeyedArchiver and NSKeyedUnarchiver to make TwentyFour apps exchange messages with each other? It was possible because both sides were able to encode and decode variables using the algorithm implemented by those two classes, in exactly the same way, every time. It was easy because both sides were created using the same iPhone SDK, and we were guaranteed consistency. However, once you decide to use different platforms for different sections of your app (i.e., iPhone game clients connecting to a game server that's running on Linux), you must deal with a possibility that you won't have an implementation of NSKeyedArchiver and NSKeyedUnarchiver algorithms for a particular platform that you want to use.

One common solution to this problem is to use standard, well-defined ways to format your data, such as XML, JavaScript Object Notation (JSON), and the like. You can typically find libraries that will take care of handling the low-level details of encoding and decoding for you, no matter which programming language you choose.

Another way to go about it is to "roll your own," just as we did with GKPong. You can make up your own format, and make sure that you can handle composition and parsing of messages on both the server and client end. Both approaches have their positives and negatives. Make sure to do your research before plunging into the deep end.

Warning

When dealing with cross-platform networking code, make sure to pay attention to the byte order. It's generally a good idea to convert your data to big-endian or network order before transmission. Third-party libraries usually take care of this for you, but if you do decide to come up with your own, this is something that you should keep in mind. For more information, look up "Endianness" on Wikipedia.

And a Bunch More

Once your game leaves the confines of a local network and enters rough waters of the Internet, your list of things to pay attention to will grow quite substantially. I have covered some of the challenges already, Here are a few more:

  • Security: Now that your game will be accessible to so many more people, you will want to make sure that it is protected against those who are looking to cause trouble. This includes securing your server computers and making sure that it won't be easy for players to cheat.

  • Scalability: This is a fancy word for being able to handle the demand. Popular iPhone games can get hundreds of thousands of players. Can your server handle that many? Even if you don't get that many, prepare to deal with spikes in usage when your game becomes available for sale or a favorable review appears and people rush to try it out.

  • Monitoring: When something goes wrong with your servers, as happens from time to time, make sure that you are the first one to find out about it. Don't wait for your players to e-mail you a "Your game doesn't work" message, or, even worse, leave bad reviews in the App Store because they just downloaded the game and it cannot connect to the server.

Basics of Online Game Play

Even though it might feel like we just got told to fight a war twice the size with an army half of what it used to be, all is not lost. Don't let the list of challenges set you back. Problems like these have existed for as long as games have been around, and all of them can be addressed if you put in enough effort. In an online multiplayer gaming project, the stakes are higher, but so is the potential payoff, both in terms of player engagement and popularity of your app.

Let's start with simple things. As far as the game client goes, we still have CFNetwork on our side. We just need to figure out how to build a game server and where to run it.

Keep in mind that we are talking about real-time (shooters, racing, and so on) and turn-based (card or board) games here.

Client/Server Games

The vast majority of multiplayer games use the client/server model. In an iPhone game that's running over a local network, you typically bundle a server into the game app itself, just as we did with TwentyFour. However, an online game would have a dedicated piece of game server software running somewhere on a computer that's connected to the Internet. The network structure of a typical online game server setup is shown in Figure 16-1.

Online game servers can be written in a variety of languages—any language that gives you the ability to accept and establish sockets connections will do. For performance reasons, many developers choose to go with C-based languages. Usually, this comes down to using the tools that you know versus learning new ones or finding people with skills that complement your own.

Where do you run such a server? There are a couple of considerations here:

  • You need a computer that your game clients can contact from the Internet.

  • Given how popular iPhone games can get, you need a computer (or a group of computers) that is powerful enough to handle a lot of connections.

A game running on an iPhone is connected via the Internet to a central server, which takes on all of the responsibilities that our little TwentyFour server did, and then some. Typically, connections stay open for the whole duration of the gaming session, allowing bidirectional exchange of messages.

Figure 16.1. A game running on an iPhone is connected via the Internet to a central server, which takes on all of the responsibilities that our little TwentyFour server did, and then some. Typically, connections stay open for the whole duration of the gaming session, allowing bidirectional exchange of messages.

The typical answer here is to find a company that specializes in hosting services and to pay to rent or lease computers located in that company's data centers. They will typically be powerful and connected enough to handle an online multiplayer game server that has a small-to-medium-sized player base.

Connecting to a Game Server Without Bonjour

In terms of code on the client side, you can reuse the vast majority of the Connection class that we created in Chapter 15. Instead of asking NSNetService to create a pair of streams that will then be used to communicate with the server, you'll need to establish a connection to the game server explicitly, using the server's hostname (or IP address) and port number.

If you are interested in having this functionality in your other apps or games, I have a few more lines of code for you. Load the TwentyFour project from Chapter 15, open Connection.h, and add a method with the following signature:

- (id)initWithHostName:(NSString*)hostName portNumber:(int)portNumber;

Now, somewhere in Connection.m, add the implementation:

- (id)initWithHostName:(NSString*)hostName portNumber:(int)portNumber {
CFReadStreamRef readStream;
  CFWriteStreamRef writeStream;
  CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)hostName, portNumber,
      &readStream, &writeStream);
  self.inputStream = (NSInputStream*)readStream;
  self.outputStream = (NSOutputStream*)writeStream;
  return self;
}

This method is very similar to the initWithNativeSocketHandle: method that we created earlier, but instead of pairing streams with a native socket handle, we are instructing the operating system to create a socket based on the hostname and port number. Note that the actual connection will not be opened until you call Connection's connect method.

Peer-to-Peer Games

If you lift the hood of the GameKit framework and look at the internals of GKSession, you'll find that it mostly uses Bonjour to find peers, and a networking protocol called UDP to exchange data between peers. What makes UDP different from TCP (which we used in TwentyFour) is that it doesn't have a notion of a connection. You simply specify which IP address and port you want to send a bunch of bytes to, and the operating system tries to deliver the data for you. When using UDP, the networking layer does not guarantee that your packets will be delivered or in what order they will get there. If you want to transmit data reliably, you need to implement an algorithm that will do so. (Does this remind you of GKSendDataReliable versus GKSendDataUnreliable?)

It should come as no surprise that you, too, can use UDP in your apps, via CFNetwork. In theory, you can use it to reimplement GKPong to be playable online. And since Bonjour is not available, you'll need a centralized server that will allow your peers to find each other. The basic structure of a peer-to-peer setup is illustrated in Figure 16-2.

In practice, there are quite a few issues with using UDP over the Internet to implement online peer-to-peer games—most of them having to do with bypassing firewalls and ensuring that peers can connect to each other. This is the main reason why a lot of developers decide to go with a client/server option instead, which is simpler but might result in additional latency.

Tip

If you want to learn more about designing peer-to-peer networking protocols using UDP, make sure to pick up a copy of iPhone Cool Projects (Apress, 2009) and read Chapter 2, entitled "Mike Ash's Deep Dive into Peer-to-Peer Networking."

Game clients use a centralized server to find peers, but then communicate with each other directly, allowing for lower latency.

Figure 16.2. Game clients use a centralized server to find peers, but then communicate with each other directly, allowing for lower latency.

Something About Reinventing the Wheel

At this point, you might be wondering, "Hasn't all this been done before? Do I really have to do this all myself, from scratch?" Unless you find low-level network programming interesting and are willing to invest some time into getting it right, it could be quite painful to use tools like CFNetwork directly. That's why you might want to look at the libraries and toolkits other developers have created that could be of use to you.

As of this book's writing, CocoaAsyncSocket (http://code.google.com/p/cocoaasyncsocket/) is considered to be one of the bestthird-party networking libraries to use for iPhone and/or Mac OS X development. With this library, you don't need to worry about a lot of low-level details. However, just as with any other tool that you pick up, you need to learn how to use it effectively. The API is more complex than GameKit, but it's also more powerful. Luckily, it does come with some documentation and a couple of examples.

Then there is enet (http://enet.bespin.org), a "thin, simple and robust communication layer on top of UDP." If you do need a replacement for GKSession's miraculous ability to mix and match reliable and unreliable packet delivery, enet can do it for you. Also, because it's a platform-independent framework, you can write both an iPhone game client and, say, a Linux game server, using the same library. Of course, you will need some time to learn the ropes, as usual. Also, enet is written in C, which means that you won't get to interact with classes, but will need to deal in functions and data structures, much as we needed to do when using the CFNetwork directly. But don't let these seeming inconveniences stop you from creating something great. According to Phil Hassey, the author of the award-winning real-time strategy game Galcon, the multiplayer part of that game was written using enet, and "it worked out-of-the-box."

Like a Drop in the Ocean

There is a whole lot more to building successful online multiplayer games than I can cover here. But by now, you should have a pretty good idea of how to go about it.

If you are serious about exploring this topic further, a good place to get advice and additional information is forums where game developers hang out, such as GameDev.net (http://www.gamedev.net/community/forums). For more iPhone- and Mac OS X-oriented game development, check out the iPhone Dev SDK forum (http://iphonedevsdk.com/forum/iphone-sdk-game-development) and iDevGames.com (http://idevgames.com/forum).

Making Games More Social

What if you have a game that can't really be called multiplayer—does that mean that your players are doomed to forever feeling isolated? Of course not! There are many different ways of using networking frameworks to give your game's audience a sense of connectedness and belonging. I will introduce some of these techniques in the rest of this chapter.

Sharing High Scores Online

One of the best ways to keep your players engaged with the game is to constantly give them something to strive for. For example, you can allow them to compete with each other via an online leaderboard. Implementing something like this requires having a central server, but the infrastructure is not as complex as what is required for online play, so it can be done faster and cheaper. Plus, it works for any game that awards points to players, making it one of the most basic and accessible techniques for bringing social interactions into games.

Usually, you store the scores on a central server that game clients can connect to via the Internet. Data transfer can be done via HTTP, which is the best tool to use in these circumstances. The iPhone SDK has several classes that implement this protocol for you. Take a look at NSURLRequest and NSURLConnection, and the sample code that demonstrates their use.

On the server side, you'll need several components:

  • A server computer that will run all this. If you already have a web site, using the same server would be a good starting point.

  • A place to store the scores, usually a database, such as MySQL or PostgreSQL.

  • A web server that will accept clients' requests (that is, if you do decide to go with HTTP). A typical choice for web server software is Apache.

  • A script running inside of the web server. This script will handle communication with the clients and interact with the database. This part can be implemented in a myriad of programming languages.

A sketch of what the resulting infrastructure might look like is shown in Figure 16-3.

All of the data is stored on the server. Clients submit scores when players get awarded some, and fetch them when players want to see the leaderboard.

Figure 16.3. All of the data is stored on the server. Clients submit scores when players get awarded some, and fetch them when players want to see the leaderboard.

When it comes time to present the high-score table, depending on how fast you want to implement this functionality and how integrated with your app you want the high-score table to look, you have a few options:

  • Request the list of scores from the server and display each entry in the list as a cell inside a UITableView.

  • Have the server construct and send back an HTML file that will contain a nicely formatted high-score table, which can then be rendered on the iPhone by a UIWebView.

  • Request the list of scores from the server and have the client turn it into an HTML file that can be rendered by a UIWebView.

  • Fetch scores from the server and render them on the screen using custom routines and UI elements. Let your imagination and graphics design requirements show you the way here.

Tip

For a detailed walk-through of how to implement an online leaderboard in your own game, with source code included, check out Chapter 2 of iPhone Games Projects (Apress, 2009), titled "Responsive Social Gaming with RESTful Web Services," by PJ Cabrera.

Chasing Ghosts

Once you start sharing scores, why not use the same infrastructure to allow players to record and share whole game-play performances, allowing others to replay them and compete, as if in real time? Think of a racing game. Instead of chasing a car controlled by another player over the network in real time, you could be trying to beat a car that simply follows a path recorded during a gaming session that was played by you or someone else earlier. Usually, those cars are displayed half-transparently, giving you a feeling that you are competing against a ghost. This idea can apply to several gaming genres, not just racing.

Here, instead of (or, typically, in addition to) submitting and fetching high scores, you upload and download files that contain game-play data that can be used to re-create actions taken by another player, or even the same one, in the game.

A great example of this feature can be seen in an iPhone game called DrawRace by Redlynx Ltd.

Chatting

Another great way to bring people together is to let them talk to one another. Here you have two options: text and voice.

The easiest way to implement text chat is with a client/server model, where clients send messages to and receive messages from chat rooms via a central server. When it comes to the chat protocol, you can either pick an existing one, like XMPP (also known as Jabber) or create your own. Both approaches have their positive and negative aspects. Jabber is fairly complex but powerful, allowing you to take advantage of server software that has been written already (check out an open source Jabber server implementation called Openfire at http://www.igniterealtime.org/projects/openfire/index.jsp). Making something from scratch, arguably, involves more coding and debugging, but could be easier to control and extend.

One of the interesting new features that was introduced in iPhone SDK 3.0 is the ability to establish a voice chat session between two iPhone apps. It works over Bluetooth and Wi-Fi. If you want to allow players to chat over the Internet, you will again need a central server that will allow chat participants to find each other, and to initialize the voice chat connection. For more information, search the Xcode documentation for GKVoiceChat.

Summary

Whew! We have covered a lot of ground in these four chapters on networking. You should now know how to create iPhone games that can be played over Bluetooth using GameKit, in addition to utilizing CFNetwork and Bonjour to connect players via local Wi-Fi network—and it's not a small feat! In addition to all of that, if you decide to open the doors for gamers from all over the world to compete, you should have a pretty good idea of where to begin.

Network programming is an exciting topic, from both technical and business perspectives. There is no doubt that, everything else being equal, social games attract more players and retain participants for longer periods of time—allowing you, the game developer, to be more successful.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset