Vagrant0610
@Vagrant0610
PHP разработчик

В чём роль потоков (Stream) и как они работают в передаче данных по локальной сети (через Socket)?

Здравствуйте! Пишу клиент-серверное приложение. Задача: передать файл с сервера клиенту (по запросу клиента). Файл любого формата и размера. Я писал клиент-серверные приложения, но очень простые, и это был копи пастом с небольшими доработками. При поиске в интернете, нашёл коды в которых постоянно фигурируют классы NetworkStream, BinaryReader, FileStream и т.д. Вот коды:
Вариант №1
// Отправляем:
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);

Вариант №2
// Код для приёма файла на стороне сервера
        static void uploadFile(NetworkStream ns)
        {
            byte[] buf = new byte[1024];
            int count;
            FileStream fs = new FileStream("uploadFile.txt", FileMode.Open);
            BinaryReader br = new BinaryReader(fs);
            fs.Close();
 
            byte[] sizeFile = BitConverter.GetBytes(fs.Length);
            // Передаем размер файла
            ns.Write(sizeFile, 0, sizeFile.Length);
 
            Thread.Sleep(500);
            BinaryFormatter formater = new BinaryFormatter();
 
            while ((count = br.Read(buf, 0, 1024)) > 0)
            {
                formater.Serialize(ns, buf);
            }
        }
 
        // Код для передачи файла на стороне клиента
        static void sendFile(Socket client, NetworkStream ns)
        {
            byte[] buffe = new byte[client.ReceiveBufferSize];
            // ns = NetworkStream
            ns.Read(buffe, 0, buffe.Length);
            int sizeFile = BitConverter.ToInt32(buffe, 0);
 
            MemoryStream ms = new MemoryStream();
            BinaryFormatter formater = new BinaryFormatter();
 
            while (sizeFile > ms.Length)
            {
                ms.Write((byte[])formater.Deserialize(ns), 0, 1024);
                //sizeFile -= 1024;
            }
            File.WriteAllBytes("sendFile.txt", ms.ToArray());
        }

Как я вижу принцип работы отправки файла по сети: Перед отправкой файла, устанавливается соединение и файл отправляется, но перед отправкой, конвертируется в байты. А потом я не могу понять принцип работы... Файл преобразовывается в байты? Весь файл преобразовывается или только часть? И как эти части отправляются (если часть)? Или как отправляется весь файл? В общем "тут мои полномочия всё...".

Вопрос: Как вообще это всё работает? Я вижу циклы в которых байты записываются в поток (stream), как я понимаю. Но никогда не вижу что бы они отправлялись (то есть метод (Socket) client.Send("А здесь например отправить поток")). И вообще не вижу ничего что говорит о том что сокет как-то используется, вижу манипуляции с байтами (как я полагаю), причём в процессе судя по всему происходит отправка файла. Объясните пожалуйста, как это работает? Буду очень благодарен!Причём тут поток и как этот поток влияет на отправку байтов по сети. Причём без метода Send. И в чём смысл метода Send? Когда вызывается метод Send, отправляется поток?
  • Вопрос задан
  • 303 просмотра
Пригласить эксперта
Ответы на вопрос 1
petermzg
@petermzg
Самый лучший программист
Stream это просто удобный абстрактный класс для работы с потоками данных.
Класс TcpClient на его базе реализует свой класс, который можно получить так
stream = tcpClient.GetStream();
И теперь все байты, что пишутся в данный stream, через переопределенные методы Write, WriteAsync, WriteByte, BeginWrite отсылаются по установленному сетевому соединению.

PS: Любой файл это изначально набор байт, так что преобразований, как у вас в примере, не требуется.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы