2012-04-27 60 views
1

背景:插座EndReceive訂單/數據問題

我編程使用異步套接字(使用BeginSend,EndSend,BeginReceive,EndReceive)彼此之間發送數據的應用程序。 IPV4上的套接字是TCP,沒有套接字標誌。

它使用系統發送一個4字節(int)消息,然後是一個消息,其長度在前一條消息中指定。我使用處理MessageLength和MessageBody的函數助手。流程是這樣的

  1. BeginReceive()
  2. EndReceive()
  3. MessageLengthReceived()
  4. BeginReceive()
  5. MessageBodyReceived()

問題:

當我發送文件數據時,問題到達時,大小爲16kb(帶有額外的小開銷:偏移量,pieceIndex等)。偶爾,當收到MessageLength時,它會從前一個消息中的隨機部分接收數據,而不是實際的消息長度。這個問題的一部分是,它並不總是發生在一個設置的偏移量(例如文件/塊/ 16 kb塊的開始或結束),並可能發生在任何文件,但發生更多,如果我發送更多的文件/更大的文件。

有內部消息發送(例如RequestMessages),從未遇到此問題。所有內部消息都是< 100個字節。

我試過等待文件塊完全保存,然後再請求另一個塊,但仍然失敗。我也嘗試限制一次發送多少個區塊,但是這隻能解決使用127.0.0.1(本地客戶端)而不是跨網絡(LAN)的問題。

我花了幾個小時瀏覽我的應用程序,看看是否有任何問題,但我還沒有看到它將發送錯誤的數據作爲標題。這個問題總是出現在兩個客戶端的發送和接收之間。是否有設置我應該使用的套接字/發送方法?或者它可能是某種競爭條件(我曾考慮過競態條件,但事實是數據可以隨機存放在一個文件中,這讓我重新思考這一點)。

+0

聽起來像您的代碼中的錯誤。這將是一個猜謎遊戲,沒有一個簡短的自包含代碼示例。 – spender 2012-04-27 20:09:28

+0

你可能是對的。我忙於工作atm,我會看看我是否可以在今晚晚些時候添加一些更具體的代碼。 – Mike 2012-04-27 21:20:37

回答

0

從這個問題,我想你正在處理的問題是在MonoTorrent庫裏面。

我自己從未遇到過這樣的問題。通過查看這些代碼,我認爲接收部分已經訂購了,因爲網絡IO在第一個處理之前不會嘗試接收第二個消息。 PieceMessages的寫請求也在DiskIO中排隊,所以不應該是問題。

但是,在發送過程中,可以從幾個地方調用ProcessQueue函數。並且由ProcessQueue調用的EnqueueSendMessage間接不會實際將消息排入任何隊列。它只是簡單地調用Socket.BeginSend。我不知道Socket.BeginSend()裏面是否有任何隊列機制。如果沒有,當多個線程試圖使同一套接字「BeginSend」不同的數據時,這可能會帶來一些問題。

+0

不完全是單調的,但非常相似(我做了一些自定義修改)。零碎的長度發生了變化,因此ChunkLength是錯誤的。我相應地更新了它,它工作正常。榮譽的連接雖然! – Mike 2012-05-04 23:57:41