[英]Socket Listener Multiple Simultaneous AcceptAsync Calls
因此,我一直在研究套接字編程,並繼續閱讀創建高性能服務器的方法。
閱讀有關使用Socket
的AcceptAsync
方法的信息,以及當連接立即可用時,有時調用如何同步執行(並返回false),以及如何在接受連接后使套接字回到監聽狀態,我開始想知道這是否意味着確實,盡管接受使用AcceptAsync
的套接字的套接字將異步“等待”,但最終即使一次連接1000個客戶端,一次也只能處理1個新連接,具體取決於將客戶端傳遞給另一個線程的速度。處理,可能會限制性能。
然后,這使我想知道是否可以考慮使用所有連接使用SocketAsyncEventArgs
的單個實例,而不是本來打算使用的對象池來編寫類。
我對此進行了更多思考,我想知道在這種情況下,如果在沒有可用連接的情況下進行多個AcceptAsync
調用會發生什么情況。 因此,我制作了這個非常非常粗糙的測試應用程序,以了解會發生什么:
class Program
{
private static Socket s;
static void Main(string[] args)
{
s = new Socket(IPAddress.Any.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
s.Bind(new IPEndPoint(IPAddress.Any, 10001));
s.Listen(10);
var e = new SocketAsyncEventArgs();
e.Completed += EOnCompleted;
s.AcceptAsync(e);
e = new SocketAsyncEventArgs();
e.Completed += EOnCompleted;
s.AcceptAsync(e);
e = new SocketAsyncEventArgs();
e.Completed += EOnCompleted;
s.AcceptAsync(e);
e = new SocketAsyncEventArgs();
e.Completed += EOnCompleted;
s.AcceptAsync(e);
while (true)
{
}
}
private static void EOnCompleted(object sender, SocketAsyncEventArgs socketAsyncEventArgs)
{
Console.WriteLine(socketAsyncEventArgs.AcceptSocket.RemoteEndPoint);
Thread.Sleep(10000);
var e = new SocketAsyncEventArgs();
e.Completed += EOnCompleted;
s.AcceptAsync(e);
}
}
我使用了一個tcp測試應用程序來向應用程序發送帶有連接的垃圾郵件,結果表明,多個AcceptAsync
調用創建了多個似乎並行執行的Accept / Complete周期。
我的問題是,這實際上有什么好處嗎? 這是允許更快處理傳入連接的合法方法嗎? 有什么缺點嗎?
編輯1:進一步研究這似乎在技術上是可能的,如果數據始終可用於異步調用的處理,則它們將全部同步運行,並且永不返回以接受新連接,或者至少會出現嚴重的延遲。
如果確實如此,如何生產高性能服務器?
通常,僅需要以下代碼:
while (true) {
var socket = listener.Accept();
Task.Run(async () => await RunConnectionAsync(socket));
}
此代碼的用戶模式部分將很快運行。 幾乎所有時間都將花費在內核上。 這將很快接受連接。 由於內核管理的積壓,不會刪除任何連接。
很少需要有多個未完成的接受呼叫來實現您的性能目標。 如果確實需要,只需在多個線程上運行相同的代碼即可。
SocketAsyncEventArgs
API已過時。 基於任務的IO更加方便,並且占用大量CPU。
特別是,如果為每個操作創建一個新的SocketAsyncEventArgs
,則將失去該模式的所有好處。 那沒有意義。
在幾乎所有情況下,都不需要異步IO從套接字接受。 執行將花費更多的CPU時間,因此延遲會稍長一些。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.