多线程游戏服务器的基本设计?

时间:2010-09-30 20:22:04

标签: c++ multithreading game-loop

如何编写多线程游戏服务器?

如果有4个线程,是否有一个线程运行游戏循环,3个接受和处理请求?另外:是从运行游戏循环的线程发送的信息吗?

2 个答案:

答案 0 :(得分:0)

Starkey已经指出,它在很大程度上取决于精确的设计。

例如,在拥有许多客户端的游戏中,您需要为处理输入分配专用线程,但对于具有少量客户端的游戏(例如< = 16),则不需要多个线程。

有些游戏具有相当聪明的NPC功能。在自己的线程上运行它们可能很聪明,但是如果你有太多,你需要一个线程池,所以一堆NPC可以共享一个线程。

如果你有一个持久的世界,你需要将状态写入某个地方的硬盘(可能通过数据库)。由于这有严重的延迟,你不希望在I / O上有一个主游戏循环等待。那将是另一个主题。

最后,还有一个问题是你是否有一个游戏循环。 MMO会有一个循环吗,或者你宁愿拥有多个?

答案 1 :(得分:0)

主要关键是确保您的游戏逻辑不受线程模型的影响。

因此,大多数游戏服务器看起来像这样:

main() {

  gGlobalReadOnlyStuff = LoadReadOnlyStuff();

  SpawnThreads(numCores); // could be another limiting resource...
  WaitForThreadsToBeReadyToGo();

  while(1) {
     WaitForNetworkInput(networkInput);

     switch(networkInput.msg) {

     case ADMIN_THING:  // start/stop websever, dump logs, whatever...
          DoAdminThing(networkInput.params);  
          break;

     case SPAWN_GAME: // replace 'game' with 'zone' or 'instance' as needed
          idThread = ChooseBestThread(); // round robin, random, etc
          PostStartGameMessageToThread(idThread, networkInput.msg);
          break;

     // ...

     }
  }

}

void ThreadUpdate() {

   threadLocalStuff = LoadThreadLocalStuff();

   SignalThreadIsReadyToGo();   

   while(1) {

   lock(myThreadsMessageQueue);
   // copy messages to keep lock short
   localMessageQueue = threadsMessageQueue;
   unlock(myThreadsMessageQueue);

   foreach(message in localMessageQueue) {
       switch(message.msg) {
       case SPAWN_GAME:
           threadLocalStuff.games.MakeNewGame(message.params));
           break;
       case ADMIN_THING__LET_EVERYONE_KNOW_ABOUT_SERVER_RESET:
           ...;
           break;
       // etc...
       }
   }


   foreach(game in threadLocalStuff.games) {
       game.Update(); // game will handle its own network communication
   }
}

然后,两个艰难的事情是“提出适合你游戏的分区(游戏,区域,实例,无论什么)”和“跨越这些界限的过渡事物(玩家,火球,史诗乐团)”一个典型的答案是“通过数据库序列化“,但你可以使用套接字/消息/文件/等等。但是,在哪里以及如何制作这些分区并最大限度地减少跨越边界的内容与您的游戏设计密切相关。

(是的,根据您的设置,可能有一些“共享”系统(日志记录,内存)可能需要多线程处理(或者甚至更好,每个线程只有一个记录器/堆))