2010-10-21 260 views
1

您好我正在編寫多線程客戶端服務器的任務。 到目前爲止,我所做的是在一個端口中打開一個套接字,並分叉兩個線程以便傾聽和寫入客戶端。但我需要將兩種類型的客戶端連接到服務器並以不同的方式提供服務。我的問題是什麼將是我最好的方法?多線程客戶端服務器

我正在處理具有無限循環接受連接的類中的連接。當連接被接受時,這個類創建兩個線程來讀寫客戶端?現在,如果我想處理另一種不同類型的客戶,我們應該怎麼做?

我需要打開另一個端口嗎?還是有可能通過同一個端口服務?可能是,如果可以識別套接字中的客戶端類型比我可以以不同的方式處理消息。

或者你是否建議這樣嗎?

  1. 爲兩種類型的客戶端分叉兩個線程,並監視不同端口中每個線程中的入站連接。
  2. 當一個連接接受每個線程產生另外兩個線程進行監聽和寫入。

請提出建議。

回答

0

不同的協議通常在不同的端口上提供服務。但是,您可以通過協商要使用的協議,通過同一端口爲兩種類型的客戶端提供服務。這可以像客戶發送HELOEHLO一樣簡單來請求一種或另一種服務。

4

也許你會從Unix用戶得到更好的答案,但我會提供我所知道的。

您的服務器需要一個線程來打開等待傳入連接的「偵聽」套接字。這個線程可以作爲簡單的主線程,但是如果你關心UI交互的話,它可以是一個備用線程(例如在Windows中,這是一個擔心,對Unix沒有把握)。這聽起來像你至少這麼遠。

當「偵聽」套接字接受連接時,您會看到一個連接到「客戶端」套接字的「連接」套接字。您可以將此「連接」套接字傳遞給一個新線程,該線程管理從寫入「連接」套接字的讀數。因此,我建議的一個改變是在一個線程中管理'連接'套接字,而不是像你所做的那樣在兩個單獨的線程中(一個用於讀取,一個用於寫入)。使用select()系統調用可以完成對相同套接字的讀寫操作,如here所示。

當新的客戶端連接時,您的'偵聽'套接字將提供一個新的'連接'套接字,您將切換到另一個線程。此時,您有兩個線程 - 一個管理第一個連接,一個管理第二個連接。就套接字而言,客戶之間沒有區別。你只需要兩個開放的連接,一個連接到你的兩個客戶端。

在這一點上,問題變成了「爲他們提供不同的服務」意味着什麼。如果客戶希望以獨特的方式與服務器交互,那麼必須以某種方式確定。交互可以根據您可以查詢的'客戶端'套接字的IP地址來確定,但這似乎是任意的,並且會受到網絡更改的影響。它也可以基於從'客戶'套接字接收到的指示所需交互類型的初始數據塊。在這種情況下,管理'連接'套接字的線程可以讀取預期類型交互的套接字,然後將套接字交給管理該交互類型的類對象。

我希望這會有所幫助。

1

您可以在一個線程中處理單個客戶端連接上的讀寫操作。基於多線程的最簡單的解決方案將是這樣的:

// C++ like pseudo-code 
while (server_running) 
{ 
    client = server.accept(); 
    ClientHandlingThread* cth = CreateNewClientHandlingThread(client); 
    cth->start(); 
} 

class ClientHandlingThread 
{ 
    void start() 
    { 
     std::string header = client->read_protocol_header(); 
     // We get a specific implementation of the ProtocolHandler abstract class 
     // from a factory, which create objects by inspecting some protocol header info. 
     ProtocolHandler* handler = ProtocolHandlerFactory.create(header);   
     if (handler) 
      handler->read_write(client); 
     else 
      log("unknown protocol") 
    }  
}; 

爲了擴展更好,你可以使用一個線程池,而不是產生一個新的線程爲每個客戶。有許多free thread pool實現for C++

while (server_running) 
{ 
    client = server.accept(); 
    thread_pool->submit(client); 
    cth->start(); 
} 

服務器可以通過使用一些實現reactor pattern的框架進一步改進。他們在引擎蓋下使用selectpoll功能。您可以直接使用這些功能。但對於生產系統來說,最好使用現有的反應器框架。 ACE是用於開發高度可擴展的併發應用程序的最廣爲人知的C++工具包之一。