2012-03-30 61 views
2

我不得不传输大文件,此时我使用TcpClient和NetworkStream类来做到这一点,但它不够。当我使用NetworkStream.Write和读取它丢失字节我不知道如何确保TCP将停止读取时,所有字节将确定。TcpClient VS Socket在大文件传输中

然后我发现Socket Class,现在我的问题是“Socket在结束读取之前会完全确定所有字节?”

如何recive文件:

  byte[] VideoFrom = new byte[FizeSizeSendedBefore]; 
      byte[] PartData = new byte[clientSocket.ReceiveBufferSize]; 
      int PartNumbers = (VideoSize/clientSocket.ReceiveBufferSize) + 1; 
      int lastPackageSize = VideoSize - ((PartNumbers - 1) * clientSocket.ReceiveBufferSize); 

      int i; 
      int bytesToRead = 0; 
      int ActualSize = 0; 
      for (i = 0; i < PartNumbers; i++) 
      { 
       if (i < PartNumbers - 1) 
       { 
        bytesToRead = clientSocket.ReceiveBufferSize; 
       } 
       else 
       { 

        bytesToRead = lastPackageSize; 
       } 
       ActualSize += bytesToRead; 


       PartData = new byte[bytesToRead]; 

       System.Threading.Thread.Sleep(2); 

       networkStream.Read(PartData, 0, bytesToRead); 

       Buffer.BlockCopy(PartData, 0, VideoFrom, i * clientSocket.ReceiveBufferSize, bytesToRead); 
      } 



      if (!Directory.Exists("./temp/anwsers/" + AnwserXML.Attribute("number").Value)) { Directory.CreateDirectory("./temp/anwsers/" + AnwserXML.Attribute("number").Value); } 
      File.WriteAllBytes("./temp/anwsers/" + AnwserXML.Attribute("number").Value + "/" + AnwserXML.Attribute("client").Value + ".mov", VideoFrom); 


     } 

如何将文件发送

int PartNumber = (FizeSizeSendedBefore/ clientSocket.ReceiveBufferSize) + 1; 
      int lastPackageSize = FileSize - ((PartNumber - 1) * clientSocket.ReceiveBufferSize); 
      int i; 
      for (i = 0; i < PartNumber; i++) 
      { 
       if (i < PartNumber - 1) 
       { 
        while (!serverStream.CanRead) { } 
        serverStream.Write(outStream, i * clientSocket.ReceiveBufferSize, clientSocket.ReceiveBufferSize); 
       } 
       else 
       { 
        while (!serverStream.CanRead) { } 
        serverStream.Write(outStream, i * clientSocket.ReceiveBufferSize, lastPackageSize); 
       } 

      } 
+4

我敢肯定它*不*输字节。我确定这个问题存在于你的代码中 - 但是很难说出你的代码在什么地方...... – 2012-03-30 09:47:01

+0

我更新了我的问题 – 2012-03-30 10:03:00

+0

这对loaclhost来说一切正常,但在局域网并不好。 – 2012-03-30 10:12:24

回答

0

多大的文件?也许这将是足够的WebClient.DownloadDataAsync(...)

更新 如果文件是需要约100MB使用简单的Web客户端:)

 WebClient wc = new WebClient(); 
     wc.DownloadDataCompleted += new DownloadDataCompletedEventHandler(OnDownloadDataCompleted); 
     wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(OnDownloadProgressChanged); 
     wc.DownloadDataAsync(new Uri("http://www.xxxx.com/t.tar.gz")); 
+0

我很难说。但我认为10MB> – 2012-03-30 10:03:32

0

TCP将在同一时间接收的数据块 - 它不会丢失数据,但如果你不迎合事实上,数据将被分散到数据包中,并且会一个接一个地(通常)不是一个大的“文件”,那么您可能不会听取其余的数据 - 这看起来好像缺少数据,但真的是代码在收到第一个数据包后忽略其余部分。只是因为你把它放在一个柱子里,这并不意味着它会一次到达。

在谷歌的美妙世界中,有很多TCP服务器/客户端应用程序(和聊天应用程序)的例子供您比较笔记 - 或者张贴您的代码,然后我们可以看到错误的位置。

+0

我更新了我的问题 – 2012-03-30 10:02:49

6

这就是问题所在:

networkStream.Read(PartData, 0, bytesToRead); 

决不忽视的Read返回值。 从不假设一次读取的呼叫将读取所有的数据。你需要循环,阅读,直到全部“进入”。读取所有数据所需的Read的调用次数与Write的调用次数几乎无关。 TCP是协议 - 对待它。

目前还不清楚您是否确切知道您期望读取多少数据 - 对吗?服务器会在最后关闭连接吗?如果是这样,如果你正在使用.NET 4,那么你就可以摆脱一个巨大量此准则:

using (Stream output = File.Create(filename)) 
{ 
    networkStream.CopyTo(output); 
}