Upcoming Events
Unite 2010
11/10 - 11/12 @ Montréal, Canada

GDC China
12/5 - 12/7 @ Shanghai, China

Asia Game Show 2010
12/24 - 12/27  

GDC 2011
2/28 - 3/4 @ San Francisco, CA

More events...
Quick Stats
62 people currently visiting GDNet.
2406 articles in the reference section.

Help us fight cancer!
Join SETI Team GDNet!
Link to us Events 4 Gamers
Intel sponsors gamedev.net search:

Contents
 Introduction
 Data Packets
 Multicasting
 in Games


 Source code
 Printable version
 Discuss this article

Uses of Multicasting in Games

I can think of two ways straight away - one is to use it for reducing (maybe even eliminating) the amount of repeated data that a server has to send out, but another interesting use is a global server-less interface for finding other players on the network.

The scenario: there are 2 people on a large network running the same game that want to play together, but they don't know each other's IP addresses let alone the fact that the potential opponent exists. The common ways for connecting the 2 players:

  • The players send out a broadcast message to the entire network, however this would create huge traffic and will probably be restricted to sub networks. Broadcasting on the Internet would create an enormous amount of traffic, so it is not allowed.
  • The players connect to an intermediate, "known" master server IP, which tells them of each other's existence. These servers are costly to run and their uptime is often undependable.
  • The players go to a chatroom hoping to find other players and play together. This will not connect all the players as some may be in different chatrooms. And the process of finding someone may take a while.

So here we are with an age old problem (how A finds B) on one hand and multicasting on the other. Multicasting groups always have the same address - a "known" address as in the case of a dedicated server, they are online 100% of the time - unlimited uptime, they don't cost anything to connect to or send information across. All game clients simply connects to a multicast group, multicast an "I want to play" message and the servers can then advertise their availability directly (instead of broadcasting, to save bandwidth) to the clients who are members of the multicast group.

Sure, there are itsy-bitsy technical problems to sort out, but the idea is cool enough. And the TTL control allows us to query within a certain range of routers (see TTL table) so we can specifically only ask to send to our LAN, or a university network, or all servers within our country to respond. Don't you think that is COOL? I sure do.

The only problem (see "The Dark Side") remains multicast support by ISP's and networks. So the best way to add multicasting to a game is still as an option (although I hope and pray that multicasting will be 100% supported in the future). But how do we integrate multicasting into our game as an option?

Integrating Multicasting into Games

Ok then, where do we start? There are so many different types of multiplayer games that I won't even try to explain how to integrate multicasting into different types of games. Instead I'll just give a few possible ideas of solutions in a client-server relationship.

First of all, all the current network code should be kept as it is, when you add multicast support make sure you do not remove any existing code unless you really think it is necessary.

When adding multicast support, you can either do a parallel integration where multicasting runs along with existing code, or you could write two separate sets of network code and add a 'multicast on/off switch' for the user. The on/off switch would isolate servers using the other network code and add one more daunting and mysterious switch for the average newbie to get wrong. Parallel integration (bah, the things I learned in school last year) is my favorite as it will use multicasting only if it is supported and should be transparent to the user.

So let’s stick with parallel integration - in this case the normal network code runs always, but the multicasting code only runs if multicasting is supported. How do we determine if multicasting is supported? Just read the error setsockopt() gives us when trying to join a group:

nRet = setsockopt(hUDPSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                  (char*)&mreq, sizeof(mreq));
if(WSAESOCKTNOSUPPORT == nRet)
  {
  // Multicasting not supported. Damn.
  }

The client-server relationship is a game of two halves. So what if the server supports multicasting while the client does not? How does the server know which clients are covered with a single send to the multicast group and which are not? The client first determines that it does not support multicasting, then connects to the server and tells the server whether it supports multicasting. The server usually keeps a list or array of clients, to which it is easy to add an extra boolean flag:

struct Client
  {
  SOCKADDR_IN addrRemote;
  /* ... Game specific info here ...*/
  BOOL bSupportMulticast;
  }

The server's function to send data sends a multicast to clients who support multicasting and normal UDP datagrams to those that do not. If, however, the server itself does not support multicasting then we must use the old method. Here's a useful code snippet for a server with multicasting as an option:

int SendToAll(char *Data)
  {
  if(bServerSupportMulticast)
    {
    // First send multicast, then send individually
    // to those who don't support it
    for(int index = 0; index < MAX_CLIENTS; index++)
    {
      if(Clients[index].Exist && Clients[index].bSupportMulticast)
      {
        // At least one client supports multicasting, so use it
        SendMulticast(Data, addrMulticast);
        break;
      }
    }
    for(int index = 0; index < MAX_CLIENTS; index++)
      {
      if(Clients[index].Exist && !Clients[index].bSupportMulticast)
        {
        OldSendToClient(Data, Clients[index].addrRemote);
        }
      }
    }
  else
    {
    // Use the old method all the way regardless of support
    // as we ourselves don't support it
    for(int index = 0; index < MAX_CLIENTS; index++)
      {
      if(Clients[index].Exist)
        {
        OldSendToClient(Data, Clients[index].addrRemote);
        }
      }
    }
  }

I hope I've shed some light on multicasting and its possible uses in games. If you've found this article the least bit interesting or have a problem, drop an email to denis@voxelsoft.com. I hope to write another article soon, but for now, Happy Multicasting!

- Denis "Voxel" Lukianov
Thanks to Jan "Riva" Halfar for the wonderful diagrams.