From 0275ef1bb1b641d0941efb1e91c7131981d6e1a1 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Sat, 6 Jan 2024 03:11:58 +0600 Subject: [PATCH] FSP simplified --- DTLib.Network/DTLib.Network.csproj | 2 +- DTLib.Network/FSP.cs | 114 ++++++++++++----------------- DTLib.Network/Package.cs | 69 +++++++++++------ 3 files changed, 93 insertions(+), 92 deletions(-) diff --git a/DTLib.Network/DTLib.Network.csproj b/DTLib.Network/DTLib.Network.csproj index cec6661..a418fc5 100644 --- a/DTLib.Network/DTLib.Network.csproj +++ b/DTLib.Network/DTLib.Network.csproj @@ -2,7 +2,7 @@ DTLib.Network - 1.3.1 + 1.3.2 Timerix Some sick network protocols GIT diff --git a/DTLib.Network/FSP.cs b/DTLib.Network/FSP.cs index f69dc71..f1c6f33 100644 --- a/DTLib.Network/FSP.cs +++ b/DTLib.Network/FSP.cs @@ -1,18 +1,24 @@ -using DTLib.Dtsod; - -namespace DTLib.Network; +namespace DTLib.Network; // // передача файлов по сети // public class FSP { + public int BufferSize { get; init; } = 512 * 1024; + + readonly byte[] buffer; + Socket MainSocket { get; init; } - public FSP(Socket _mainSocket) => MainSocket = _mainSocket; + public FSP(Socket _mainSocket) + { + buffer = new byte[BufferSize]; + MainSocket = _mainSocket; + } - public uint BytesDownloaded { get; private set; } - public uint BytesUploaded { get; private set; } - public uint Filesize { get; private set; } + public long BytesDownloaded { get; private set; } + public long BytesUploaded { get; private set; } + public long Filesize { get; private set; } // скачивает файл с помощью FSP протокола public void DownloadFile(IOPath filePath_server, IOPath filePath_client) @@ -21,8 +27,8 @@ public class FSP filePath_client.ThrowIfEscapes(); lock (MainSocket) { - MainSocket.SendPackage("requesting file download".ToBytes(StringConverter.UTF8)); - MainSocket.SendPackage(filePath_server.Str.ToBytes(StringConverter.UTF8)); + MainSocket.SendPackage("requesting file download"); + MainSocket.SendPackage(filePath_server.Str); } DownloadFile(filePath_client); } @@ -31,8 +37,7 @@ public class FSP { filePath_client.ThrowIfEscapes(); using System.IO.Stream fileStream = File.OpenWrite(filePath_client); - Download_SharedCode(fileStream, true); - fileStream.Close(); + Download_SharedCode(fileStream); } public byte[] DownloadFileToMemory(IOPath filePath_server) @@ -40,8 +45,8 @@ public class FSP filePath_server.ThrowIfEscapes(); lock (MainSocket) { - MainSocket.SendPackage("requesting file download".ToBytes(StringConverter.UTF8)); - MainSocket.SendPackage(filePath_server.Str.ToBytes(StringConverter.UTF8)); + MainSocket.SendPackage("requesting file download"); + MainSocket.SendPackage(filePath_server.Str); } return DownloadFileToMemory(); } @@ -49,49 +54,30 @@ public class FSP public byte[] DownloadFileToMemory() { using var fileStream = new System.IO.MemoryStream(); - Download_SharedCode(fileStream, false); - byte[] output = fileStream.ToArray(); - fileStream.Close(); - return output; + Download_SharedCode(fileStream); + return fileStream.ToArray(); } - private void Download_SharedCode(System.IO.Stream fileStream, bool requiresFlushing) + private void Download_SharedCode(System.IO.Stream fileStream) { lock (MainSocket) { BytesDownloaded = 0; - Filesize = MainSocket.GetPackage().BytesToString(StringConverter.UTF8).ToUInt(); - MainSocket.SendPackage("ready".ToBytes(StringConverter.UTF8)); - int packagesCount = 0; - byte[] buffer = new byte[5120]; - int fullPackagesCount = (int)(Filesize / buffer.Length); - // получение полных пакетов файла - for (byte n = 0; packagesCount < fullPackagesCount; packagesCount++) + Filesize = BitConverter.ToInt64(MainSocket.GetPackage(), 0); + if (Filesize < 0) + throw new Exception("FileSize < 0"); + MainSocket.SendPackage("ready"); + int recievedCount; + do { - buffer = MainSocket.GetPackage(); - BytesDownloaded += (uint)buffer.Length; - fileStream.Write(buffer, 0, buffer.Length); - if (requiresFlushing) - { - if (n == 100) - { - fileStream.Flush(); - n = 0; - } - else n++; - } - } - // получение остатка - if ((Filesize - fileStream.Position) > 0) - { - MainSocket.SendPackage("remain request".ToBytes(StringConverter.UTF8)); - buffer = MainSocket.GetPackage(); - BytesDownloaded += (uint)buffer.Length; - fileStream.Write(buffer, 0, buffer.Length); - } + recievedCount = MainSocket.Receive(buffer); + fileStream.Write(buffer, 0, recievedCount); + BytesDownloaded += recievedCount; + } while (recievedCount == buffer.Length); + + if (BytesDownloaded != Filesize) + throw new Exception($"expected {Filesize} bytes, but downloaded {BytesDownloaded} bytes"); } - if (requiresFlushing) - fileStream.Flush(); } // отдаёт файл с помощью FSP протокола @@ -100,31 +86,21 @@ public class FSP filePath.ThrowIfEscapes(); BytesUploaded = 0; using System.IO.FileStream fileStream = File.OpenRead(filePath); - Filesize = File.GetSize(filePath).ToUInt(); + Filesize = fileStream.Length; lock (MainSocket) { - MainSocket.SendPackage(Filesize.ToString().ToBytes(StringConverter.UTF8)); + MainSocket.SendPackage(BitConverter.GetBytes(Filesize)); MainSocket.GetAnswer("ready"); - byte[] buffer = new byte[5120]; - int packagesCount = 0; - int fullPackagesCount = (int)(Filesize / buffer.Length); - // отправка полных пакетов файла - for (; packagesCount < fullPackagesCount; packagesCount++) + int readCount; + do { - fileStream.Read(buffer, 0, buffer.Length); - MainSocket.SendPackage(buffer); - BytesUploaded += (uint)buffer.Length; - } - // отправка остатка - if ((Filesize - fileStream.Position) > 0) - { - MainSocket.GetAnswer("remain request"); - buffer = new byte[(Filesize - fileStream.Position).ToInt()]; - fileStream.Read(buffer, 0, buffer.Length); - MainSocket.SendPackage(buffer); - BytesUploaded += (uint)buffer.Length; - } + readCount = fileStream.Read(buffer, 0, buffer.Length); + MainSocket.Send(buffer, 0, readCount, SocketFlags.None); + BytesUploaded += readCount; + } while (readCount == buffer.Length); + + if (BytesUploaded != Filesize) + throw new Exception($"expected {Filesize} bytes, but uploaded {BytesDownloaded} bytes"); } - fileStream.Close(); } } diff --git a/DTLib.Network/Package.cs b/DTLib.Network/Package.cs index 45a0d4b..8c35c01 100644 --- a/DTLib.Network/Package.cs +++ b/DTLib.Network/Package.cs @@ -8,48 +8,72 @@ public static class Package // принимает пакет public static byte[] GetPackage(this Socket socket) { - int packageSize = 0; - byte[] data = new byte[2]; + int ppackageLength = 0; // цикл выполняется пока не пройдёт 2000 мс for (ushort s = 0; s < 400; s += 1) { - if (packageSize == 0 && socket.Available >= 2) + if (ppackageLength == 0 && socket.Available >= 4) { - socket.Receive(data, data.Length, 0); - packageSize = data.ToInt(); + byte[] ppackageLengthBytes = new byte[4]; + socket.Receive(ppackageLengthBytes); + ppackageLength = BitConverter.ToInt32(ppackageLengthBytes, 0); } - if (packageSize != 0 && socket.Available >= packageSize) + else if (ppackageLength != 0 && socket.Available >= ppackageLength) { - data = new byte[packageSize]; - socket.Receive(data, data.Length, 0); + var data = new byte[ppackageLength]; + socket.Receive(data); return data; } else Thread.Sleep(5); } throw new Exception($"GetPackage() error: timeout. socket.Available={socket.Available}"); } + public static void GetPackage(this Socket socket, byte[] buffer) + { + int packageLength = 0; + // цикл выполняется пока не пройдёт 2000 мс + for (ushort s = 0; s < 400; s += 1) + { + if (packageLength == 0 && socket.Available >= 4) + { + byte[] ppackageLengthBytes = new byte[4]; + socket.Receive(ppackageLengthBytes); + packageLength = BitConverter.ToInt32(ppackageLengthBytes, 0); + } + else if (packageLength != 0 && socket.Available >= packageLength) + { + if (buffer.Length < packageLength) + throw new Exception("buffer length is less than package length"); + socket.Receive(buffer); + } + else Thread.Sleep(5); + } + throw new Exception($"GetPackage() error: timeout. socket.Available={socket.Available}"); + } // отправляет пакет - public static void SendPackage(this Socket socket, byte[] data) + public static void SendPackage(this Socket socket, byte[] data) => SendPackage(socket, data, data.Length); + public static void SendPackage(this Socket socket, byte[] buffer, int dataLength) { - if (data.Length > 65536) - throw new Exception($"SendPackage() error: package is too big ({data.Length} bytes)"); - if (data.Length == 0) + if (buffer.Length < dataLength) + throw new Exception($"SendPackage() error: buffer is too small ({buffer.Length} bytes of {dataLength})"); + if (dataLength < 1) throw new Exception($"SendPackage() error: package has zero size"); - var list = new List(); - byte[] packageSize = data.Length.IntToBytes(); - if (packageSize.Length == 1) - list.Add(0); - list.AddRange(packageSize); - list.AddRange(data); - socket.Send(list.ToArray()); + + byte[] ppackageLength = BitConverter.GetBytes(buffer.Length); + if (ppackageLength.Length != 4) + throw new Exception("wrong with int to byte[] conversion"); + socket.Send(ppackageLength); + socket.Send(buffer, 0, dataLength, SocketFlags.None); } - public static void SendPackage(this Socket socket, string data) => SendPackage(socket, data.ToBytes(StringConverter.UTF8)); + + public static void SendPackage(this Socket socket, string data) + => SendPackage(socket, data.ToBytes()); // получает пакет и выбрасывает исключение, если пакет не соответствует образцу public static void GetAnswer(this Socket socket, string answer) { - string rec = socket.GetPackage().BytesToString(StringConverter.UTF8); + string rec = socket.GetPackage().BytesToString(); if (rec != answer) throw new Exception($"GetAnswer() error: invalid answer: <{rec}>"); } @@ -59,5 +83,6 @@ public static class Package socket.SendPackage(request); return socket.GetPackage(); } - public static byte[] RequestPackage(this Socket socket, string request) => socket.RequestPackage(request.ToBytes(StringConverter.UTF8)); + public static byte[] RequestPackage(this Socket socket, string request) + => socket.RequestPackage(request.ToBytes()); }