2012-07-25 75 views
3

我最初在發送數據時有一個競爭條件,問題是我允許使用多個SocketAsyncEventArgs發送數據,但第一個數據包在第二個數據包之前沒有完全發送,是因爲我有它,所以如果數據不適合緩衝區,它會循環直到發送所有數據,並且第一個數據包比第二個數據包很小,所以第二個數據包被髮送併到達客戶端在第一個包之前。按照SocketAsyncEventArgs的順序發送數據

我已經解決了這個問題,方法是將一個SocketAyncEventArgs分配給用於發送數據的打開連接,並使用信號量來限制對它的訪問,並在完成後返回SocketAsyncEventArgs。

現在,這工作正常,因爲所有的數據發送,回撥完成後準備下一次發送。與此相關的問題是,當我想隨機發送數據到打開的連接時,以及當發送大量數據阻止我的線程時,它導致阻塞。

我正在尋找解決這個問題的方法,我想有一個隊列,當請求發送數據時,它只是將數據包添加到隊列中,然後1個SocketAsyncEventArgs只是循環發送該數據。

但是我怎樣纔能有效地做到這一點,同時仍然是可擴展的?我希望儘可能避免阻塞,同時按照請求發送的順序發送我的數據包。

感謝任何幫助!

回答

4

如果數據需要按順序保存,並且您不想阻塞,那麼您需要添加一個隊列。我這樣做的方式是通過跟蹤我的狀態對象來確定我們是否已經爲該連接處理了一個活動的發送異步循環。排隊(這顯然必須同步)之後,只是檢查什麼是正在進行:

public void PromptToSend(NetContext context) 
    { 
     if(Interlocked.CompareExchange(ref writerCount, 1, 0) == 0) 
     { // then **we** are the writer 
      context.Handler.StartSending(this); 
     } 
    } 

這裏writerCount是寫循環的次數(這應該是完全0或1)上的連接;如果沒有,我們開始一個。我的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; 
     } 

有意義嗎?

+0

所以我會做一個隊列,當某些東西被添加到隊列中時,檢查一下發送操作是否已經在進行中,如果不是,那麼啓動一個並且它一直循環直到隊列爲空?一旦發送隊列中的隊列變爲空,則將寫入計數更改爲0,並在需要時重新啓動發送進程? – Matty 2012-07-25 12:12:07

+0

@mattysouthall正好。請注意,「保持循環」有一個* async *循環,而不是一個常規循環('while')等等。所以基本上,每當你得到「完成」事件,並且你檢查了它是OK等,然後啓動下一個去。 – 2012-07-25 13:03:12

+0

全部完成,工作很棒!我的日誌顯示它正在按照我想要的方式行事,謝謝! – Matty 2012-07-25 15:20:56

相關問題