2011-10-14 28 views
3

我已經完成了我的研究,並且我知道實現高性能套接字服務器的最佳方式通常如下:使用異步套接字操作(專用SocketAsyncEventArgs/Operations以獲得最佳性能)異步回調,將請求推送到線程池傾向的處理隊列。超高性能套接字服務器 - 實現細節

我的問題,這個處理模型 - 有最大的性能:

1)時,應在插座的「結束」操作被調用(例如EndAccept或EndReceive)?應該在排隊請求之前在回調線程(IOCP)上調用它?或者在請求從隊列中取出並被處理(工作線程)時調用?

2)這個問題取決於#1的答案。何時應該調用下一個「開始」操作?我們應該在我們調用EndOperation之前調用它,還是應該在EndOperation之後立即調用它(排隊/處理請求之前)?

3)處理隊列可以簡單地爲.NET線程池嗎?使用.NET線程池與推出自己的同步處理隊列有什麼優點/缺點?

任何幫助,非常感謝。

+1

你沒有做好你的研究:SocketAsyncEventArgs和Begin/End是兩種不同的模式。你不打電話給當您調用ReceiveAsync時EndReceive。 – dtb

+0

關於#1,應該在回調和外部調用'EndXXX'操作(如果請求同步完成)。把它做正確有點棘手。看到這個[post](http://blogs.msdn。com/b/mjm/archive/2005/05/04/414793.aspx)進行解釋。如果你想避免這種情況並使用更優雅的解決方案,我建議你使用TPL和它的'FromAsync'。 –

+1

@dtb你是對的,模型略有不同,但兩種模式都遵循通過回調進行異步處理的整體概念,我的問題仍然與 – shyneman

回答

2

1)EndReceive應該是你在異步回調中做的第一件事。事實上,除非你呼叫EndReceive,否則你不能在回調中做其他任何事情,因爲這就是你接收到的數據的原因。請參閱Socket.EndReceive上的示例。

同樣的事情發生在EndAccept之上,因爲它爲您提供了與之通信的套接字。

2)您應該在EndAccept之後儘快致電BeginAccept。否則,如果接受回調需要太長時間來處理,則可能會丟失連接請求。當然,如果你接受回調需要很長時間來做任何事情,你做錯了。同樣的事情發生在BeginReceive:儘快在EndRead之後致電,以避免數據丟失。或者,如果您的通信協議是請求/響應模型,那麼在發送更多數據之前客戶端需要響應,您可以等到調用BeginRead後再發送響應。

3)處理可能是.NET線程池,但如果你打算使用它,你應該使用Task Parallel Library進行研究。使用TPL的好處是它非常「火,忘了」,或者「火,它會在完成後回電。」使用TPL的缺點是您的應用程序更難以知道哪些任務正在處理中。如果您創建了自己的同步處理隊列,則您始終知道哪些作業正在等待處理,並且您有可能檢查隊列,取消作業等。如果要使用TPL執行此操作,則最終會創建一組任務你必須管理,因爲有no way to get the the list of pending tasks

但是,如果您不需要查看未完成的任務,那麼TPL應該可以正常工作。

這裏的相關問題有一些很好的信息。

+0

有關。關於#1,我想補充一點,儘管標準APM模式是比這更復雜一點。因爲堆棧可能在幼稚實現中溢出。首先,如果請求同步完成,還應在回調之外調用EndXXX方法。這裏有一個[blog](http://blogs.msdn.com/b/mjm/archive/2005/05/04/414793.aspx)。儘管如果使用TPL,這是照顧的。 –

+0

對於#1:如果在不調用Endxxx的情況下對整個asyncresult進行排隊,是不是可以提前釋放IOCP線程?對於#2,我認爲我們可以同意應該儘快調用它,以便可以在接受緩衝區中處理下一個連接。對於#3,我會看看TPL ......感謝所有人的建議。 – shyneman

+0

@IlianPinzon那麼你是說Endxxx方法應該在處理工作者線程內而不是套接字IOCP線程中調用?並感謝您建議TPL。 – shyneman