2010-09-30 62 views
0

多线程游戏服务器是如何编写的?多线程游戏服务器的基本设计?

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

+4

也许吧。这取决于软件的要求和设计。没有通用的方法来做到这一点。 – Starkey 2010-09-30 20:28:43

+2

你是如何选择魔术数字4的? – 2010-09-30 20:33:30

+0

这是我机器上的内核数量。 – Derp 2010-09-30 20:36:56

回答

0

斯塔基已经指出,这取决于精确的设计。例如,在有许多客户端的游戏中,你需要分配专门的线程来处理输入,但对于有少数客户端的游戏(比如说< = 16),则不需要多个线程。

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

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

最后,还有一个问题,你是否有主要游戏循环。一个MMO会有一个单一的循环,还是你有更多的?

+0

我将如何实现多个游戏循环? – Derp 2010-10-01 21:21:23

+0

我怀疑“每个线程一个”不是你正在寻找的答案。但实质上,这是“如何”的一部分。我怀疑你实际上是在“为什么”之后,这是因为运行更多的事件处理循环允许你每秒处理更多的事件。 – MSalters 2010-10-04 08:45:13

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 
    } 
} 

两个硬的东西则是“想出一个分区(游戏区,例如,无论)适合您的游戏”和“跨越这些界限过渡事物(玩家,火球,史诗lootz)'一个典型的答案是“通过数据库序列化它”,但是你可以使用套接字/消息/文件/任何东西。但是,是的,在哪里以及如何制作这些分区以及如何最小化跨越边界的内容与您的游戏设计密切相关。 (是的,根据您的设置,可能需要多线程处理(甚至更好,每个线程只有一个记录器/堆)的几个“共享”系统(日志记录,内存))