2010-09-30 105 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)'一個典型的答案是「通過數據庫序列化它」,但是你可以使用套接字/消息/文件/任何東西。但是,是的,在哪裏以及如何製作這些分區以及如何最小化跨越邊界的內容與您的遊戲設計密切相關。 (是的,根據您的設置,可能需要多線程處理(甚至更好,每個線程只有一個記錄器/堆)的幾個「共享」系統(日誌記錄,內存))