none
Передача файлов по сети. RRS feed

  • Вопрос

  • Здравствуйте!

    Сейчас работаю с сетью, вот возник такой вопрос, а как передать файл по сети от клиента к серверу (использую TcpListener и TcpClient).

    Я себе это представляю так:

    Клиент: Цикл, который читает файл фрагментами по 128 байт и тут же отправляет эти фрагменты по сети.

    Сервер: Цикл принимающий эти фрагменты и записывающий "на лету" в файл, данные которого были заранее отправленны (будущее расположение, название, тип, размер, мб MD5 для верности)

     

    Вопросы: Как прочитать файл фрагментами по 128 байт? Не будет ли сбоев/потери фрагментов в связи с тем что чтение из файла происходит быстрее чем отправка по сети? Какой оптимальный размер фрагмента файла? Буду признателен за пример с комментами.

    • Перемещено Tagore Bandlamudi 3 октября 2010 г. 0:36 MSDN Forums consolidation (От:Форум по .NET Framework)

Ответы

  • FileStream stream = File.OpenRead(@"d:\1.txt");
    byte[] buffer = new byte[128];
    // в цикле
    int bytesRead = stream.Read(buffer, 0, 128);
    
    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23
    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23
  •     int BytesRead;
    
        do
        {
          BytesRead = Stream.Read(Buffer, 0, Buffer.Length);
          if (BytesRead > 0)
          {
            Writing.Write(Buffer, 0, BytesRead);
          }
        }
        while (BytesRead == Buffer.Length);
    

    Если не поможет - сравни исходный файл и результат через fc /b.

    Вопрос #2 - посмотри линку от Megano выше.

    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23
  • Уффф....
    Все победил, все работает... Спасибо за помошь друзья. Кому интересно вот код:

    Отправляем:

      SInfo.StringsWriter.Write("123.exe");
                            SInfo.StringsWriter.Write("C:");
                            string FileName = @"D:\Шара\Gish_v1.3_RUS.exe";
                            FileStream Stream = File.OpenRead(FileName);
                            byte[] Buffer = new byte[128];
                            byte[] BytesInArray;
                            int BytesRead = -1;
                            while (BytesRead != 0)
                            {
                                BytesRead = Stream.Read(Buffer, 4, 124);
                                BytesInArray = BitConverter.GetBytes(BytesRead);
                                BytesInArray.CopyTo(Buffer, 0);
                                SInfo.StringsWriter.Write(Buffer);
                            }
                            Stream.Close();
                            Console.WriteLine("Transfer complete");

     

    и получаем:

      ClInfo[IDClient].StringsWriter.Write("Name");
                        string FileName = ClInfo[IDClient].StringsReader.ReadString();
                        LogWrite("Имя файла определенно - " + FileName, ConsoleColor.DarkYellow);
                        ClInfo[IDClient].StringsWriter.Write("Folder");
                        string FolderName = ClInfo[IDClient].StringsReader.ReadString();
                        LogWrite("Путь к папке определен - " + FolderName, ConsoleColor.DarkYellow);
                        FileStream Writing = File.OpenWrite(FolderName + @"\" + FileName);
                        byte[] Buffer = new byte[128];
                        byte[] BytesInArray = BitConverter.GetBytes(-1);
                        BytesInArray.CopyTo(Buffer, 0);
                        LogWrite("Начинаю прием файла " + FileName, ConsoleColor.DarkYellow);
                        while (BitConverter.ToInt32(Buffer, 0) != 0)
                        {
                            Buffer = ClInfo[IDClient].StringsReader.ReadBytes(128);
                            Writing.Write(Buffer, 4, BitConverter.ToInt32(Buffer, 0));
                        }
                        LogWrite("Файл " + FileName + " успешно получен!", ConsoleColor.DarkGreen);
                        Writing.Close();
                        LogWrite("Файл " + FileName + " сохранен в папке " + FolderName + "!", ConsoleColor.DarkGreen);


    Извеняюсь что код непричесан, кому нужны объяснения по коду стучите в личку.
    Еще раз всем спасибо!

    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23

Все ответы

  • Зачем такие сложности?

    В итоге с вашим алгоритмом вы передадите куда больше информации чем весит сам файл. TCP транспортный протокол который гарантирует доставку.

     

    TCP — это транспортный механизм, предоставляющий поток данных, с предварительной установкой соединения, за счёт этого дающий уверенность в достоверности получаемых данных, осуществляет повторный запрос данных в случае потери данных и устраняет дублирование при получении двух копий одного пакета (см. также T/TCP). В отличие от UDP, гарантирует, что приложение получит данные точно в такой же последовательности, в какой они были отправлены, и без потерь.
  • Спасибо за справку, а как же мне всетаки прочитать фрагментами файл и отправить его получателю/серверу? Или вы хотите сказать что мне не нужно его читать кусками? В таком случае подскажите методы в сторону которых смотреть...

    Пример кода пожалуйста.

  • FileStream stream = File.OpenRead(@"d:\1.txt");
    byte[] buffer = new byte[128];
    // в цикле
    int bytesRead = stream.Read(buffer, 0, 128);
    
    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23
    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23
  • Спасибо, то что нужно! Только вот такая проблемка, набросал код чтобы пощупать как это работает:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.IO;

    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                string FileName = @"D:\Шара\333.txt";
                string WriteName = @"D:\Шара\123.txt";
                FileStream Stream = File.OpenRead(FileName);
                FileStream Writing = File.OpenWrite(WriteName);
                byte[] Buffer = new byte[128];
                int BytesRead = -1;
                while (BytesRead != 0)
                {
                    BytesRead = Stream.Read(Buffer, 0, 128);
                    Console.Write(BytesRead.ToString() + " - ");
                    Writing.Write(Buffer, 0, BytesRead);
                }
                Stream.Close();
                Writing.Close();
                Console.Read();
            }
        }
    }

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

    Вопрос №2 как мне передать этот массив байтов по сетке используя вышеупомянутое подключение?

    Причем! Не работает после такой передачи лишь экзешник написанный на Autoit, другие программы такого поведения не проявляют, ни код написанный на C# ни мини игра, ни даже архив... Что может быть не так?

  •     int BytesRead;
    
        do
        {
          BytesRead = Stream.Read(Buffer, 0, Buffer.Length);
          if (BytesRead > 0)
          {
            Writing.Write(Buffer, 0, BytesRead);
          }
        }
        while (BytesRead == Buffer.Length);
    

    Если не поможет - сравни исходный файл и результат через fc /b.

    Вопрос #2 - посмотри линку от Megano выше.

    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23
  • Уффф....
    Все победил, все работает... Спасибо за помошь друзья. Кому интересно вот код:

    Отправляем:

      SInfo.StringsWriter.Write("123.exe");
                            SInfo.StringsWriter.Write("C:");
                            string FileName = @"D:\Шара\Gish_v1.3_RUS.exe";
                            FileStream Stream = File.OpenRead(FileName);
                            byte[] Buffer = new byte[128];
                            byte[] BytesInArray;
                            int BytesRead = -1;
                            while (BytesRead != 0)
                            {
                                BytesRead = Stream.Read(Buffer, 4, 124);
                                BytesInArray = BitConverter.GetBytes(BytesRead);
                                BytesInArray.CopyTo(Buffer, 0);
                                SInfo.StringsWriter.Write(Buffer);
                            }
                            Stream.Close();
                            Console.WriteLine("Transfer complete");

     

    и получаем:

      ClInfo[IDClient].StringsWriter.Write("Name");
                        string FileName = ClInfo[IDClient].StringsReader.ReadString();
                        LogWrite("Имя файла определенно - " + FileName, ConsoleColor.DarkYellow);
                        ClInfo[IDClient].StringsWriter.Write("Folder");
                        string FolderName = ClInfo[IDClient].StringsReader.ReadString();
                        LogWrite("Путь к папке определен - " + FolderName, ConsoleColor.DarkYellow);
                        FileStream Writing = File.OpenWrite(FolderName + @"\" + FileName);
                        byte[] Buffer = new byte[128];
                        byte[] BytesInArray = BitConverter.GetBytes(-1);
                        BytesInArray.CopyTo(Buffer, 0);
                        LogWrite("Начинаю прием файла " + FileName, ConsoleColor.DarkYellow);
                        while (BitConverter.ToInt32(Buffer, 0) != 0)
                        {
                            Buffer = ClInfo[IDClient].StringsReader.ReadBytes(128);
                            Writing.Write(Buffer, 4, BitConverter.ToInt32(Buffer, 0));
                        }
                        LogWrite("Файл " + FileName + " успешно получен!", ConsoleColor.DarkGreen);
                        Writing.Close();
                        LogWrite("Файл " + FileName + " сохранен в папке " + FolderName + "!", ConsoleColor.DarkGreen);


    Извеняюсь что код непричесан, кому нужны объяснения по коду стучите в личку.
    Еще раз всем спасибо!

    • Помечено в качестве ответа JusteG 17 мая 2010 г. 14:23