大文件传输中的TcpClient VS Socket

本文关键字:TcpClient VS Socket 文件 传输 | 更新日期: 2023-09-27 18:29:26

我必须处理大文件,此时我使用TcpClient和NetworkStream类来完成,但它还不够。当我使用NetworkStream。写入和读取它会丢失字节时,我不知道如何确保TCP在所有字节都正常时停止读取。

然后我找到了Socket类,现在我的问题是,"Socket在结束读取之前会完全确定所有字节吗?"

我如何接收文件:

            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);
                }
            }

大文件传输中的TcpClient VS Socket

这就是问题所在:

networkStream.Read(PartData, 0, bytesToRead);

Never忽略Read的返回值永远不要假设一次读取调用将读取所有数据。你需要循环阅读,直到全部"入内"。读取所有数据所需的对Read的调用数量与对Write的调用数量几乎无关。TCP是一个协议-以这种方式对待它。

目前还不清楚你是否确切知道你希望阅读多少数据——是吗?服务器最后会关闭连接吗?如果是这样的话,如果你使用的是.NET4,那么你就可以去掉大量的代码:

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

TCP将一次接收一块数据-它不会丢失数据,但如果你不考虑数据将被拆分成数据包,并将一个接一个地到达,(通常)不是一个大的"文件",那么你可能不会监听其余的数据-这看起来像是丢失了数据,但实际上它是在接收到第一个分组之后忽略其余部分的代码。仅仅因为你把它放在一列中,并不意味着它会一次性到达。

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

您的文件有多大?也许WebClient.DownloadDataAsync(...)就足够了?

更新如果文件大约为100Mb,请使用简单的WebClient:)

        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"));