2009-05-19 88 views
2

我試圖從概念上通過一個客戶端 - 服務器套接字應用程序的模型工作,我正在寫在C#(客戶端和服務器)。我的服務器需要一次處理多個客戶端,最好是同時處理來自客戶端的多個請求。我已經爲我的通信制定了一個容器,我將在每封郵件的開頭髮送一個固定長度的郵件頭,其中包含郵件的長度(包括其他內容)。我有一些在C#中使用套接字編程的經驗,所以我很喜歡使用異步套接字。C#客戶端 - 服務器協議/模型問題

我在概念上遇到的主要問題是我需要客戶端和服務器都能夠隨時接收消息。客戶端將建立連接,並保持「登錄狀態」(如IM客戶端),並且需要在任意時間接收數據並在任意時間發出請求。作爲我的協議的一部分,我還希望接收每個請求的響應(無論是從服務器到客戶端還是從客戶端到服務器)。

我希望能夠使用一個單一的套接字,如果可能的話。我相信我可以使用兩個套接字來完成這項工作,一個用於製作服務器 - >客戶端請求,另一個用於客戶端 - >服務器請求,但我不想處理兩個端口/連接的額外複雜問題。但是,使用單個套接字時,我不確定如何管理髮送請求並在可以交織時獲取響應。

我在我的搜索中找不到任何類似服務器或客戶端的示例。感謝任何提供任何ide的人。

回答

2

如果您使用的是TCP,那麼您必須在服務器端每個客戶端都有一個套接字,並且套接字要監聽連接。對於UDP,您可以使用一個套接字完成此操作。無論如何,對於您的一個UDP套接字或每個TCP客戶端套接字,請執行以下操作:

當您發生必要事件時(即用戶按下按鈕或傳入消息時,始終有BeginReceiveBeginWrite你需要做點什麼)。

編輯:作爲對您的評論的迴應,我會處理它的方式是將請求ID包含在您的標題中。無論何時發送請求(來自任一端)都包含該消息的唯一值。使用Dictionary<RequestId, RequestState>(適當替換類型)並查看傳入消息是否與預先存在的請求相關。此外,你可以指定與高位集中的所有ID都起源於客戶,並與清除高位請求ID是從服務器,以避免衝突:

Server      Client 
Request 0x00 -------------> Starts processing 

Starts processing <------- (unrelated) Request 0x80 

Request 0x00 complete <---- Sends response to 0x00 

Sends response to 0x80 ---> Request 0x80 complete 

這是系統,AOL的奧斯卡協議使用(可能很慢)的有狀態請求。編輯2:嗯,好的...你真的想阻止它嗎?你可以做的是有一個單獨的線程處理Send/Receive調用。該線程將通過線程安全的「發送消息」隊列和類似的「收到的消息」僞線隊列與主線程進行通信。我稱之爲僞隊列的原因是,你希望能夠從隊列中取消消息。主線程會在發送隊列中放置一條消息,然後阻塞接收隊列。每次套接字線程更新接收隊列時,主線程都會喚醒並檢查它想要的消息是否存在。如果是,它將採取(無序)並完成所需的操作。如果消息還沒有,它就會再次阻塞隊列。當操作最終完成時,它將恢復正常操作,並按順序從接收隊列中獲取消息並處理它們或執行其他操作。

這是否有意義?我很抱歉,如果它有點混亂...

+0

是的。但假設服務器從客戶端請求一些需要一段時間的東西。與此同時,客戶端向服務器請求了一些東西。在我的服務器的BeginReceive中,我如何知道這些傳入數據是來自客戶端的請求還是對服務器請求的響應?這就是我正在努力的。我掌握了異步套接的基礎知識。謝謝。 – Jarrod 2009-05-19 21:46:25

3

套接字是雙向的。您只需要一個套接字就可以在兩個端點之間來回發送數據。但是在客戶端上,您可能需要有一個線程不斷從套接字中讀取數據,並通知某個組件或對接收到的數據進行排隊,以便在其他地方處理它,而另一個線程通過同一個套接字發送數據。這樣你有異步通信。

但在服務器端,您需要打開一個ServerSocket,它將綁定到TCP端口並接受該端口上的連接;你接受的每一個連接都是一個新的Socket。因此,每個客戶端都有一個套接字,並且每個客戶端可能需要一個線程。

您需要爲將通過套接字傳遞的消息建立協議。你可以釀造你自己的協議或者看一個,取決於你想做什麼。通常情況下,您將首先發送兩個或四個字節,其長度爲消息的其餘部分,因此另一方知道從流中讀取很多字節;這是一個信息。消息的開始通常是消息類型;在一個非常簡單的情況下,可以說「1」是客戶端請求,「2」是服務器響應,「3」是客戶端迴應,「4」是服務器迴應響應,「5」是服務器回聲,「6」是客戶端迴應響應等。這樣,您收到一條消息,解析它,然後知道它是來自客戶端的請求,或者是對服務器發送的消息的響應。