TCP File Transfer - ошибка в нескольких байтах

1

В настоящее время я работаю над программой на С#, которая позволяет пользователю отправлять файл по сети и собирать его на другом конце. Все работает отлично, за исключением того, что несколько байтов были помещены в место назначения, оставляя его как не совсем тот же файл, с которого он начинался. (Коррупция изображений, например). Изменение: по крайней мере, когда на моем компьютере я заметил, что ошибка может быть решена, если клиент ждет одну секунду, прежде чем начать читать из потока, это дает мне представление о том, что клиент время от времени попадает в конец потока и читает что-то другое. Любая идея, как исправить это лучше, чем просто ждать второй, как с другими компьютерами, я не знаю, будет ли это работать. Код для моего сервера выглядит следующим образом:

TcpListener listener = new TcpListener(13);
        listener.Start();
        FileStream inputStream = File.OpenRead(loadLocation.Text);//loadLocation being a text box with the file path
        FileInfo f = new FileInfo(loadLocation.Text);
        int size = unchecked((int)f.Length);//Get the file size in Bytes
        int  csize = size / 4096;//Get the size in chunks of 4kb;

           statusLabel.Text = "Waiting for connection...";
            TcpClient client = listener.AcceptTcpClient();
            statusLabel.Text = "Connection accepted.";
            NetworkStream ns = client.GetStream();
            byte[] byteSize = BitConverter.GetBytes(size);//Sends the number of bytes to expect over the network
            try
            {
                ns.Write(byteSize, 0, byteSize.Length);
                byte[] temp = new byte[4096];
                for (int i = 0; i < csize; i++)
                {
                    inputStream.Read(temp, 0, 4096);
                    ns.Write(temp, 0, 4096);
                }
                byte[] end = new byte[size % 4096];
                inputStream.Read(end, 0, size % 4096);
                ns.Write(end, 0, size % 4096);
                ns.Close();
                inputStream.Close();
                client.Close();
                done = true;
                statusLabel.Text = "DONE!";
            }
            catch (Exception a)
            {
                Console.WriteLine(a.ToString());
            }
        listener.Stop();

Код клиента выглядит следующим образом:

try
        {
            FileStream outputStream = File.OpenWrite(saveLocation.Text);
            TcpClient client = new TcpClient("127.0.0.1", 13);

            NetworkStream ns = client.GetStream();

            byte[] byteTime = new byte[sizeof(int)];
            int bytesRead = ns.Read(byteTime, 0, sizeof(int));
            int size;
            size = BitConverter.ToInt32(byteTime, 0);
            int csize = size / 4096;
            byte[] temp = new byte[4096];
            for (int i = 0; i < csize; i++)
            {
                ns.Read(temp, 0, 4096);
                outputStream.Write(temp, 0, 4096);
            }
            byte[] end = new byte[size % 4096];
            ns.Read(end, 0, size % 4096);
            outputStream.Write(end, 0, size % 4096);
            ns.Close();
            outputStream.Close();
            client.Close();
            statusLabel.Text = "DONE!";

        }
        catch (Exception a)
        {
            Console.WriteLine(a.ToString());
        }

Я знаю, что TCP гарантирует порядок доставки, и я не знаю, что может быть причиной проблемы с выходным файлом. Другая заметка заслуживает того, что каждый раз, коррупция несколько отличается, например, при передаче изображения будет большой знак в другой точке изображения.

Теги:
tcp

1 ответ

1
Лучший ответ

Ваш код должен учитывать, что NetworkStream (и большинство TCP sockets вообще) не обязательно возвращает полное количество первоначально запрошенных байтов.

Microsoft пишет:

Операция "Чтение" считывает столько данных, сколько доступно, до количества байтов, заданных параметром размера.

Добавьте внешний цикл вокруг операций чтения, чтобы убедиться, что буфер заполнен. Также было бы целесообразно сделать еще несколько ошибок.

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

  • 0
    Большое спасибо, я бы проголосовал за ваш ответ, если бы у меня было больше репутации.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню