我正在用C#編寫一個聊天服務器,自下而上。「廣播」到TCP客戶端列表的最快方法
這就像一個大房間,所有的客戶,然後你可以發起私人聊天。我還將代碼放在了多個房間的未來整合中(但現在不需要)。
它的寫作主要是爲了好玩,但也因爲我要爲像我這樣的年輕人制作新的聊天室,因爲丹麥沒有人離開這裏。
我剛剛用170個客戶端進行了測試(使用JQuery和Flash橋寫入套接字連接)。發送給它的消息在本地網絡上的響應時間不到1秒。但現在我正在考慮能夠從中擠出什麼樣的表現。
我可以看到,如果我連接兩個客戶端,然後再連接其他客戶端,然後在客戶端2上寫入並觀察客戶端1,它立即出現在客戶端1上。CPU使用率和RAM使用率根本不顯示服務器壓力的跡象。它處理得很好,我認爲它可以擴展到至少1000 - 1500,沒有絲毫問題。
但是我注意到了一些事情,那就是如果我再次打開170個客戶端並在客戶端1上發送消息並在客戶端170上觀察,則會有大約750毫秒左右的日誌。 我知道這個問題,也就是說,當服務器收到一條聊天消息時,它會將它廣播給服務器上的每個客戶端。但是,它需要枚舉所有這些客戶端,並且需要時間。現在的延遲對於聊天來說是非常可以接受的,但我擔心客戶端1發送給客戶端750可能(尚未測試)需要2 - 3秒。而且,當我開始收到每秒2-3條信息時,我也很擔心。
所以總結起來,我想加快服務器的廣播過程。我已經在使用一個並行的foreach循環,而且我也使用異步套接字。
這裏是廣播代碼:
lock (_clientLock)
{
Parallel.ForEach(_clients, c =>
{
c.Value.Send(message);
});
}
這裏是正在調用的每個客戶端上的發送功能:
try {
byte[] bytesOut = System.Text.Encoding.UTF8.GetBytes(message + "\0");
_socket.BeginSend(bytesOut, 0, bytesOut.Length, SocketFlags.None, new AsyncCallback(OnSocketSent), null);
}
catch (Exception ex) { Drop(); }
我想知道是否有什麼辦法可以加快這個嗎? 我已經考慮寫一些幫助類接受消息在一個隊列中,然後使用大概20個線程左右來拆分廣播列表。
但我想知道你對這個話題的看法,我是一名學生,我想學習! (:
順便說一句,我喜歡當你的代碼在發佈到堆棧溢出時發現問題。我現在使用重載函數接受來自服務器類的字節數組,所以UTF- 8轉換隻需要發生一次,同時爲了安全起見,字節數組長度的計算現在只發生一次,參見下面的更新版本 但我仍然對改進這種方法感興趣!
更新的廣播功能:
lock (_clientLock)
{
byte[] bytesOut = System.Text.Encoding.UTF8.GetBytes(message + "\0");
int bytesOutLength = bytesOut.Length;
Parallel.ForEach(_clients, c =>
{
c.Value.Send(bytesOut, bytesOutLength);
});
}
客戶對象上更新發送功能:
public void Send(byte[] message, int length)
{
try
{
_socket.BeginSend(message, 0, length, SocketFlags.None, new AsyncCallback(OnSocketSent), null);
}
catch (Exception ex) { Drop(); }
}
+1 Good and consise question。 – rcdmk 2012-07-21 22:33:34