Отправленный файл имеет некоторые поврежденные данные TCP сокетов .. как это исправить? - PullRequest
0 голосов
/ 05 марта 2012

У меня проблема с приложением передачи файлов ... все выглядит отлично и работает так, как должно быть ... но потом я обнаружил, что некоторые части отправленного файла повреждены.
Например, когда я отправляю видеофайл (.MP4), он был успешно отправлен, но при воспроизведении его некоторые кадры были повреждены, как на снимке. Я воспроизводил исходный файл Mp4, и изображение было настолько идеальным и никогда не выглядело как на этом снимке.
Итак, вот мой код ... Теперь я запутался в использовании fs.Seek ... кто-то сказал мне, что новый файл не совпадает с исходным файлом.

Я использую сокеты TCP .. (.Net 4.0)

enter image description here

Способ отправки (КЛИЕНТ):

FileStream fs;
long sum;
long fileSize;
byte[] data = null;
NetworkStream network; 
const int packetSize = 1024*8;

private void SendFile(string srcPath, string destPath)
    {
        string dest = Path.Combine(destPath, Path.GetFileName(srcPath));
        using (fs = new FileStream(srcPath, FileMode.Open, FileAccess.Read))
        {
            try
            {
                sum = 0;
                int count = 0;
                data = new byte[packetSize];
                //send the destination path and the file size to SERVER.
                SendCommand("receive<" + dest + "<" + fs.Length.ToString());
                while (sum < fileSize)
                {
                    if (fileSize - sum < packetSize)
                    {
                        count = fs.Read(data, 0, Convert.ToInt32(fileSize - sum));
                        network.Write(data, 0, Convert.ToInt32(fileSize - sum));
                    }
                    else
                    {
                        count = fs.Read(data, 0, data.Length);
                        network.Write(data, 0, data.Length);
                    }
                    fs.Seek(sum, SeekOrigin.Begin);
                    sum += count;
                    backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));
                }
                network.Flush();
            }
            finally
            {
                fs.Dispose();
                data = null;
            }
        }
    }

Метод получения (SERVER):

FileStream fs;
long sum;
long fileSize;
byte[] data = null;
NetworkStream network; 
const int packetSize = 1024*8;

public void Receive(string destPath, long fileSize)
    {
        using (fs = new FileStream(destPath, FileMode.Create, FileAccess.Write))
        {
            try
            {
                int count = 0;
                long sum = 0;
                data = new byte[packetSize];
                while (sum < fileSize)
                {
                    if (fileSize - sum < packetSize)
                    {
                        count = network.Read(data, 0, Convert.ToInt32(fileSize - sum));
                        fs.Write(data, 0, Convert.ToInt32(fileSize - sum));
                    }
                    else
                    {
                        count = network.Read(data, 0, data.Length);
                        fs.Write(data, 0, data.Length);
                    }
                    fs.Seek(sum, SeekOrigin.Begin);
                    sum += count;
                }
            }
            finally
            {
                fs.Dispose();
                data = null;
            }
        }
    }

Ответы [ 2 ]

3 голосов
/ 05 марта 2012

Вы никогда не учитываете, сколько байтов вы прочитали из файла или сетевого потока.Смотрите ваши count переменные в кодах вашего сервера и клиента.

Вы должны записать count байтов в другой поток после чтения из входного потока.

EDIT

Вот пример из вашего кода в Receive

count = network.Read(data, 0, data.Length);
fs.Write(data, 0, data.Length);

Как вы можете быть уверены, что прочитали data.Length байт

1 голос
/ 05 марта 2012

В случае, если вы еще не решили это, я предлагаю этот код.Поместите его внутрь while (sum

Отправьте:

    count = fs.Read(data, 0, packetSize);
    network.Write(data, 0, count);
    sum += count;
    backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));

и получите:

    count = network.Read(data, 0, packetSize);
    fs.Write(data, 0, count);
    sum += count;

Это обеспечит передачу только тех данных, которые у вас естьчитать.Обратите внимание, что вам не нужна , если часть, потому что Read вернет количество прочитанных байтов, поэтому не имеет значения, находитесь ли вы в начале или в конце файла, Read прочитает все, что может, до ограниченияВы указали в качестве параметра.

...