TcpClient VS Socket для передачи больших файлов - PullRequest
2 голосов
/ 30 марта 2012

Мне нужно переместить большой файл, в данный момент я использую классы TcpClient и NetworkStream, чтобы сделать это, но этого не достаточно.Когда я использую NetworkStream.Write и Read это теряет байты, я не знаю, как я могу гарантировать, что TCP прекратит чтение, когда все байты будут в порядке.

Затем я нашел класс 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);
                }

            }

Ответы [ 3 ]

6 голосов
/ 30 марта 2012

Это проблема:

networkStream.Read(PartData, 0, bytesToRead);

Никогда игнорировать возвращаемое значение Read. Никогда не предполагает, что один вызов read прочитает все данные.Вы должны зацикливаться, читая, пока все не "в".Количество вызовов на Read, которые требуются для чтения всех данных, в значительной степени не связано с количеством вызовов на Write.TCP - это протокол stream - относитесь к нему таким образом.

Не ясно, знаете ли вы точно, сколько данных вы ожидаете прочитать - не так ли?Будет ли сервер закрывать соединение в конце?Если это так, и если вы используете .NET 4, то вы можете избавиться от огромного количества этого кода:

using (Stream output = File.Create(filename))
{
    networkStream.CopyTo(output);
}
0 голосов
/ 30 марта 2012

TCP будет получать порцию данных за один раз - он не потеряет данные, но если вы не учитываете тот факт, что данные будут разбиты на пакеты и будут поступать один за другим, и (часто) не как одинбольшой «файл», тогда вы, возможно, не слушаете остальные данные - это может показаться, что это пропущенные данные, но на самом деле это код, игнорирующий остальное после получения первого пакета.Просто потому, что вы собрали его в один столб, это не значит, что он придет одним куском.

В замечательном мире Google можно найти множество примеров приложений сервера / клиента TCP (и приложений чата), в которых вы можете сравнить заметки - опубликуйте свой код, и тогда мы сможем увидеть, где находится ошибка.

0 голосов
/ 30 марта 2012

Насколько велик ваш файл? Может быть, этого будет достаточно WebClient.DownloadDataAsync(...)?

ОБНОВЛЕНО Если размер файла составляет около 100 МБ, используйте простой 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"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...