[英]Sending data in order with SocketAsyncEventArgs
我最初在發送數據時遇到了競爭條件,問題是我允許多個SocketAsyncEventArgs用於發送數據,但是第一個數據包在第二個數據包之前沒有完全發送,這是因為我有這樣的數據,如果數據在發送所有數據之前,它不適合它循環的緩沖區,並且第一個數據包大於第二個數據包很小,因此第二個數據包在第一個數據包之前被發送並到達客戶端。
我通過將1個SocketAyncEventArgs分配給用於發送數據的開放連接並使用信號量來限制對它的訪問來解決這個問題,並在完成后使SocketAsyncEventArgs回調。
現在這樣可以正常工作,因為所有數據都已發送,當它完全准備好下次發送時回調。 這個問題是,當我想要隨機地向開放連接發送數據時,它會導致阻塞,並且當有大量數據發送時它會阻塞我的線程。
我正在尋找一個解決這個問題的工作,我想到了一個隊列,當請求發送數據時,它只是將數據包添加到隊列中,然后1個SocketAsyncEventArgs只是循環發送該數據。
但是,如何在保持可擴展性的同時有效地做到這一點? 我希望盡可能避免阻塞,同時按照請求發送的順序發送數據包。
感謝任何幫助!
如果需要按順序保存數據,並且您不想阻止,則需要添加隊列。 我這樣做的方法是在我的狀態對象上跟蹤我們是否已經為該連接啟用了一個活動的發送異步循環。 入隊后(顯然必須同步),只需檢查正在進行的操作:
public void PromptToSend(NetContext context)
{
if(Interlocked.CompareExchange(ref writerCount, 1, 0) == 0)
{ // then **we** are the writer
context.Handler.StartSending(this);
}
}
這里writerCount
是連接上寫循環的計數(應該正好是1或0); 如果沒有,我們開始一個。
我的StartSending
嘗試從該連接的隊列中讀取; 如果它可以這樣做,它會執行通常的SendAsync
等:
if (!connection.Socket.SendAsync(args)) SendCompleted(args);
(請注意,這里的SendCompleted
用於“同步”情況;它必須通過事件模型為“異步”情況進行SendCompleted
)。 SendCompleted
顯然重復了這個“出隊,嘗試發送異步”的步驟。
剩下的唯一事情就是確保當我們試圖出列時,如果我們找不到更多的事情,我們會注意到缺乏行動:
if (bufferedLength == 0)
{ // nothing to do; report this worker as inactive
Interlocked.Exchange(ref writerCount, 0);
return 0;
}
合理?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.