[英]Multi threaded client server
嗨,我正在編寫多線程客戶端服務器的作業。 到目前為止,我所做的是在端口中打開一個套接字,並派生了兩個線程來偵聽和寫入客戶端。 但是我需要將兩種類型的客戶端連接到服務器,並為它們提供不同的服務。 我的問題是我最好的方法是什么?
我正在一個有無限循環來接受連接的類中處理連接。 只要接受了連接,該類就會創建兩個線程來讀寫客戶端? 現在,如果我要處理另一個不同類型的客戶,我們該怎么辦?
我需要打開另一個端口嗎? 還是可以通過同一端口進行服務? 也許可以確定套接字中的客戶端類型,而不是我可以不同地處理消息。
還是您建議這樣?
請提出建議。
也許您會從Unix用戶那里得到更好的答案,但是我會提供我所知道的。
您的服務器需要一個線程來打開“偵聽”套接字,以等待傳入連接。 為了簡單起見,該線程可以是主線程,但是,例如,如果您擔心UI交互,則可以是備用線程(在Windows中,這是一個問題,對於Unix不確定)。 聽起來您至少到現在為止。
當“偵聽”套接字接受連接時,您將獲得一個已連接到“客戶端”套接字的“已連接”套接字。 您可以將此“已連接”套接字傳遞給一個新線程,該線程管理“已連接”套接字的讀取和寫入。 因此,我建議進行的一項更改是在單個線程中管理“已連接”套接字,而不是像您那樣在兩個單獨的線程(一個用於讀取,一個用於寫入)中進行管理。 閱讀和寫作對同一插座可以使用來實現select()
系統調用,如這里 。
當新的客戶端連接時,您的“偵聽”套接字將提供一個新的“已連接”套接字,您將移交給另一個線程。 此時,您有兩個線程-一個線程管理第一個連接,另一個線程管理第二個連接。 就套接字而言,客戶端之間沒有區別。 您僅具有兩個打開的連接,兩個客戶端各有一個。
在這一點上,問題就變成了“為他們提供不同服務”是什么意思。 如果希望客戶端以獨特的方式與服務器交互,則必須以某種方式確定它。 可以根據您可以查詢的“客戶端”套接字的IP地址來確定交互,但這似乎是任意的,並且會受到網絡變化的影響。 它也可以基於從“客戶端”套接字接收的初始數據塊,該數據塊指示所需的交互類型。 在這種情況下,管理“已連接”套接字的線程可以讀取套接字以獲取預期的交互類型,然后將套接字交給管理該交互類型的類對象。
我希望這有幫助。
您可以在一個線程中處理單個客戶端連接上的讀寫。 基於多線程的最簡單解決方案是:
// 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")
}
};
為了更好地擴展,您可以使用線程池,而不是為每個客戶端生成新線程。 有許多C ++的 免費線程池實現。
while (server_running)
{
client = server.accept();
thread_pool->submit(client);
cth->start();
}
通過使用一些實現反應堆模式的框架,可以進一步改善服務器。 他們在后台使用select
或poll
功能。 您可以直接使用這些功能。 但是對於生產系統,最好使用現有的反應堆框架。 ACE是用於開發高度可擴展的並發應用程序的最廣為人知的C ++工具包之一。
通常在不同的端口上服務於不同的協議。 但是,可以通過協商要使用的協議來在同一端口上為兩種類型的客戶端提供服務。 這可以像客戶端發送HELO
或EHLO
來請求一種或另一種服務那樣簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.