2014-06-11 88 views
0

我正在使用以下代碼通過tcp發送文件。.NET中的TCP文件發送問題,NetworkStream Socket

如果我連續發送多次相同的文件來測試它是否健壯,我會正確接收第一個文件,而另一個則搞砸了。

所有搞砸的文件有相同的不正確的字節,如果我睡覺(一段時間)所有文件傳輸正確。我發現我必須在讀取我的文件時實例化一個新的緩衝區,以便正確地完成一切。但我不明白爲什麼。

我擔心我重新實現緩衝區的解決方案可能只是隱藏了另一個主要問題。任何建議?

using(var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read)) 
{ 
    using(var binaryReader = new BinaryReader(fileStream)) 
    { 
     var _sendingBuffer = new byte[BUFFER_SIZE]; 

     int length = (int)fileStream.Length; 
     int bytesRead = 0; 

     //Ensure we reached the end of the stream regardless of encoding 
     while (binaryReader.BaseStream.Position != binaryReader.BaseStream.Length) 
     { 
      bytesRead = binaryReader.Read(_sendingBuffer, 0, _sendingBuffer.Length); 

      _socket.BeginSend(_sendingBuffer, 0, bytesRead, SocketFlags.None, SendFileCallback, null); 

      //without this i received some messed up data 
      _sendingBuffer = new byte[BUFFER_SIZE]; 
     }  
    } 
} 
+0

發送的部分是每答案錯誤。也許接收部分也壞了。發佈代碼。 – usr

+0

請注意,依靠像HTTP這樣的標準協議更容易。套接字非常難以使用。 – usr

+0

其實發送和接收部分正在工作,我沒有尋找一種方法來完成這個東西。我無法使用Http我受許多方面的環境,需求和策略的限制(WinCE) – sam

回答

2

BeginSend是一個異步操作。只有在你打電話後才能保證開始,它不會馬上完成。只要套接字發送傳遞的數據,該數據就不能被突變。 操作結束將通過AsyncCallback回調參數發出信號。

您的問題正是您在傳輸仍在進行中時突變傳輸緩衝區。爲每個傳輸呼叫創建一個新的陣列可以解決這個問題。

其他方式來解決這個問題:

  • 使用阻斷Socket.Send功能,這將阻止,直到整個數據被髮送和緩衝區可以重複使用。這也會使您的錯誤處理更容易,因爲錯誤不會通過AsyncCallback顯示出來。
  • 使您的完整程序異步執行,例如使用C#5的異步任務和異步/等待功能 因此:
    1. 首先異步讀取文件的一部分。
    2. 當異步讀取完成異步發送它通過套接字
    3. 完成該操作後,有更多的數據讀取回到1
+0

我沒有看到關於緩衝區的說法。我認爲BeginSend可能會從本地緩衝區中複製數據,然後將請求排入隊列。你有什麼參考? – sam

+0

我可以讓所有東西排隊之前,第一個回調被稱爲和第一個EndSend被調用,並且一切都被正確接收。這似乎證明了我說的 – sam

+0

此外,我第二次調用方法時遇到第一個塊上的問題(僅當我不更新緩衝區時)。由於緩衝區是方法本地的,我不應該面對這個問題:當我調用方法時,它是一個新的緩衝區。 – sam