2011-11-25 142 views
0

我設法通過TCP使用NetworkStream和套接字發送二進制數據。 我唯一的問題是,當我發送較大的文件,如幾百KB的圖像,他們沒有得到正確的傳輸,圖像的一半丟失。在服務器端I Socket.Send傳輸數據。在客戶端,我使用Socket.BeginReceive1024大小的緩衝區,將其寫入MemoryStream,稍後使用new Bitmap(Stream)將該MemoryStream轉換爲可在PictureBox中顯示的圖像。C#通過互聯網發送文件

我應該使用什麼方法來避免數據丟失?

編輯:代碼發佈

  listener = new TcpListener(myAddress, 86); 
      listener.Start(); 
      TcpClient client = listener.AcceptTcpClient(); 
      ns = client.GetStream(); 
      byte[] buffer = new byte[1024]; 
      while (fileTransfer) 
      { 
       ms = new MemoryStream(); 
       do 
       { 
        int length = ns.Read(buffer, 0, buffer.Length); 
        ms.Write(buffer, 0, length); 
        // with this line added the data loss apparently disappears 
        System.Threading.Thread.Sleep(1); 
       } while (ns.DataAvailable); 
       UpdateData(); 
       ms.Dispose(); 
       System.Threading.Thread.Sleep(10); 
      } 
      ns.Dispose(); 
      client.Close(); 
      listener.Stop(); 

編輯:數據仍然是腐敗有時甚至與睡眠方法。

+3

請發佈您的代碼,以便發現錯誤。 – Oded

+3

發佈您的代碼。如果沒有,我們只是猜測。 – ChrisF

+0

這看起來沒問題,所以假設它不是網絡問題,在發送方或接收方都有問題,我們需要查看該代碼。 – nos

回答

0

好的我在發送實際數據之前通過發送數據的大小來解決它。它不起作用的原因是我錯誤地認爲轉移是直接的。這就是爲什麼接收器環路中的Sleep()方法有所作爲但並未解決問題的原因。我明白,在這種情況下我不能依賴DataAvailable。即使檢查接收到的數據的長度也不起作用,因爲客戶端可能在循環完成後發送數據。檢查文件大小(如果數據大於接收端的緩衝區)是我發現這麼久的最佳解決方案。

0

很可能(猜測)你沒有正確讀取客戶端的數據流。

你需要閱讀EndReceive()方法的結果,看看你實際上有多少數據讀取 - 這可能不是你的緩衝區的大小(1024個字節在這種情況下)

所以:
一)當調用BeginReceive時你是否傳遞迴調?
b)如果是,你是否正在讀取這個結果並將適當的字節數寫入你的存儲流?

即:

public void ReceiveCallback(IAsyncResult result) 
{ 

    var buffer = (byte[])result.AsyncState; 
    int bytesRead = socket.EndReceive(); 
    memoryStream.Write (buffer, 0, bytesRead);//bytesRead may not be 1024! 
} 
+0

好點,但我意識到這一點,即使仍然有數據等待傳輸,它似乎是NetworkStream.DataAvailable報告錯誤的問題。 – thencz

+2

@Tibor Hencz您誤解了DataAvailable屬性。它不會告訴你發送端可能有一些未來的數據可以發送給你,它會告訴你是否有可用的數據,在你的接收端點* NOW *處。如果你讀的速度比另一方快,那麼在這個特定的時間,沒有數據到達你的主機,但是在3納秒時,一些數據會到達?你應該繼續閱讀,直到發送端關閉流(或者直到發生大的超時) – nos

+0

是的,這正是我的代碼應該做的,檢查是否有數據到達設備並讀取它,如果有的話。我在這個示例代碼中看到它:http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.dataavailable.aspx – thencz

1

我建議你改變這種循環:

do 
{ 
    int length = ns.Read(buffer, 0, buffer.Length); 
    ms.Write(buffer, 0, length); 
    // with this line added the data loss apparently disappears 
    System.Threading.Thread.Sleep(1); 
} while (ns.DataAvailable); 

到:

do 
{ 
    int length = ns.Read(buffer, 0, buffer.Length); 
    ms.Write(buffer, 0, length); 
} while (length > 0); 

也就是說,一直讀到的數據(即ns.Read收益到底有沒有數據)。 Read阻塞,直到有一些數據或套接字關閉(或拋出一些異常)。我刪除了無用的睡眠。