FSP simplified

This commit is contained in:
Timerix22 2024-01-06 03:11:58 +06:00
parent 9d48b41e30
commit 0275ef1bb1
3 changed files with 93 additions and 92 deletions

View File

@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<!--package info--> <!--package info-->
<PackageId>DTLib.Network</PackageId> <PackageId>DTLib.Network</PackageId>
<Version>1.3.1</Version> <Version>1.3.2</Version>
<Authors>Timerix</Authors> <Authors>Timerix</Authors>
<Description>Some sick network protocols</Description> <Description>Some sick network protocols</Description>
<RepositoryType>GIT</RepositoryType> <RepositoryType>GIT</RepositoryType>

View File

@ -1,18 +1,24 @@
using DTLib.Dtsod; namespace DTLib.Network;
namespace DTLib.Network;
// //
// передача файлов по сети // передача файлов по сети
// //
public class FSP public class FSP
{ {
Socket MainSocket { get; init; } public int BufferSize { get; init; } = 512 * 1024;
public FSP(Socket _mainSocket) => MainSocket = _mainSocket;
public uint BytesDownloaded { get; private set; } readonly byte[] buffer;
public uint BytesUploaded { get; private set; }
public uint Filesize { get; private set; } Socket MainSocket { get; init; }
public FSP(Socket _mainSocket)
{
buffer = new byte[BufferSize];
MainSocket = _mainSocket;
}
public long BytesDownloaded { get; private set; }
public long BytesUploaded { get; private set; }
public long Filesize { get; private set; }
// скачивает файл с помощью FSP протокола // скачивает файл с помощью FSP протокола
public void DownloadFile(IOPath filePath_server, IOPath filePath_client) public void DownloadFile(IOPath filePath_server, IOPath filePath_client)
@ -21,8 +27,8 @@ public class FSP
filePath_client.ThrowIfEscapes(); filePath_client.ThrowIfEscapes();
lock (MainSocket) lock (MainSocket)
{ {
MainSocket.SendPackage("requesting file download".ToBytes(StringConverter.UTF8)); MainSocket.SendPackage("requesting file download");
MainSocket.SendPackage(filePath_server.Str.ToBytes(StringConverter.UTF8)); MainSocket.SendPackage(filePath_server.Str);
} }
DownloadFile(filePath_client); DownloadFile(filePath_client);
} }
@ -31,8 +37,7 @@ public class FSP
{ {
filePath_client.ThrowIfEscapes(); filePath_client.ThrowIfEscapes();
using System.IO.Stream fileStream = File.OpenWrite(filePath_client); using System.IO.Stream fileStream = File.OpenWrite(filePath_client);
Download_SharedCode(fileStream, true); Download_SharedCode(fileStream);
fileStream.Close();
} }
public byte[] DownloadFileToMemory(IOPath filePath_server) public byte[] DownloadFileToMemory(IOPath filePath_server)
@ -40,8 +45,8 @@ public class FSP
filePath_server.ThrowIfEscapes(); filePath_server.ThrowIfEscapes();
lock (MainSocket) lock (MainSocket)
{ {
MainSocket.SendPackage("requesting file download".ToBytes(StringConverter.UTF8)); MainSocket.SendPackage("requesting file download");
MainSocket.SendPackage(filePath_server.Str.ToBytes(StringConverter.UTF8)); MainSocket.SendPackage(filePath_server.Str);
} }
return DownloadFileToMemory(); return DownloadFileToMemory();
} }
@ -49,49 +54,30 @@ public class FSP
public byte[] DownloadFileToMemory() public byte[] DownloadFileToMemory()
{ {
using var fileStream = new System.IO.MemoryStream(); using var fileStream = new System.IO.MemoryStream();
Download_SharedCode(fileStream, false); Download_SharedCode(fileStream);
byte[] output = fileStream.ToArray(); return fileStream.ToArray();
fileStream.Close();
return output;
} }
private void Download_SharedCode(System.IO.Stream fileStream, bool requiresFlushing) private void Download_SharedCode(System.IO.Stream fileStream)
{ {
lock (MainSocket) lock (MainSocket)
{ {
BytesDownloaded = 0; BytesDownloaded = 0;
Filesize = MainSocket.GetPackage().BytesToString(StringConverter.UTF8).ToUInt(); Filesize = BitConverter.ToInt64(MainSocket.GetPackage(), 0);
MainSocket.SendPackage("ready".ToBytes(StringConverter.UTF8)); if (Filesize < 0)
int packagesCount = 0; throw new Exception("FileSize < 0");
byte[] buffer = new byte[5120]; MainSocket.SendPackage("ready");
int fullPackagesCount = (int)(Filesize / buffer.Length); int recievedCount;
// получение полных пакетов файла do
for (byte n = 0; packagesCount < fullPackagesCount; packagesCount++)
{ {
buffer = MainSocket.GetPackage(); recievedCount = MainSocket.Receive(buffer);
BytesDownloaded += (uint)buffer.Length; fileStream.Write(buffer, 0, recievedCount);
fileStream.Write(buffer, 0, buffer.Length); BytesDownloaded += recievedCount;
if (requiresFlushing) } while (recievedCount == buffer.Length);
{
if (n == 100) if (BytesDownloaded != Filesize)
{ throw new Exception($"expected {Filesize} bytes, but downloaded {BytesDownloaded} bytes");
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);
}
}
if (requiresFlushing)
fileStream.Flush();
} }
// отдаёт файл с помощью FSP протокола // отдаёт файл с помощью FSP протокола
@ -100,31 +86,21 @@ public class FSP
filePath.ThrowIfEscapes(); filePath.ThrowIfEscapes();
BytesUploaded = 0; BytesUploaded = 0;
using System.IO.FileStream fileStream = File.OpenRead(filePath); using System.IO.FileStream fileStream = File.OpenRead(filePath);
Filesize = File.GetSize(filePath).ToUInt(); Filesize = fileStream.Length;
lock (MainSocket) lock (MainSocket)
{ {
MainSocket.SendPackage(Filesize.ToString().ToBytes(StringConverter.UTF8)); MainSocket.SendPackage(BitConverter.GetBytes(Filesize));
MainSocket.GetAnswer("ready"); MainSocket.GetAnswer("ready");
byte[] buffer = new byte[5120]; int readCount;
int packagesCount = 0; do
int fullPackagesCount = (int)(Filesize / buffer.Length);
// отправка полных пакетов файла
for (; packagesCount < fullPackagesCount; packagesCount++)
{ {
fileStream.Read(buffer, 0, buffer.Length); readCount = fileStream.Read(buffer, 0, buffer.Length);
MainSocket.SendPackage(buffer); MainSocket.Send(buffer, 0, readCount, SocketFlags.None);
BytesUploaded += (uint)buffer.Length; BytesUploaded += readCount;
} while (readCount == buffer.Length);
if (BytesUploaded != Filesize)
throw new Exception($"expected {Filesize} bytes, but uploaded {BytesDownloaded} bytes");
} }
// отправка остатка
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;
}
}
fileStream.Close();
} }
} }

View File

@ -8,48 +8,72 @@ public static class Package
// принимает пакет // принимает пакет
public static byte[] GetPackage(this Socket socket) public static byte[] GetPackage(this Socket socket)
{ {
int packageSize = 0; int ppackageLength = 0;
byte[] data = new byte[2];
// цикл выполняется пока не пройдёт 2000 мс // цикл выполняется пока не пройдёт 2000 мс
for (ushort s = 0; s < 400; s += 1) 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); byte[] ppackageLengthBytes = new byte[4];
packageSize = data.ToInt(); 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]; var data = new byte[ppackageLength];
socket.Receive(data, data.Length, 0); socket.Receive(data);
return data; return data;
} }
else Thread.Sleep(5); else Thread.Sleep(5);
} }
throw new Exception($"GetPackage() error: timeout. socket.Available={socket.Available}"); 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) if (buffer.Length < dataLength)
throw new Exception($"SendPackage() error: package is too big ({data.Length} bytes)"); throw new Exception($"SendPackage() error: buffer is too small ({buffer.Length} bytes of {dataLength})");
if (data.Length == 0) if (dataLength < 1)
throw new Exception($"SendPackage() error: package has zero size"); throw new Exception($"SendPackage() error: package has zero size");
var list = new List<byte>();
byte[] packageSize = data.Length.IntToBytes(); byte[] ppackageLength = BitConverter.GetBytes(buffer.Length);
if (packageSize.Length == 1) if (ppackageLength.Length != 4)
list.Add(0); throw new Exception("wrong with int to byte[] conversion");
list.AddRange(packageSize); socket.Send(ppackageLength);
list.AddRange(data); socket.Send(buffer, 0, dataLength, SocketFlags.None);
socket.Send(list.ToArray());
} }
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) public static void GetAnswer(this Socket socket, string answer)
{ {
string rec = socket.GetPackage().BytesToString(StringConverter.UTF8); string rec = socket.GetPackage().BytesToString();
if (rec != answer) if (rec != answer)
throw new Exception($"GetAnswer() error: invalid answer: <{rec}>"); throw new Exception($"GetAnswer() error: invalid answer: <{rec}>");
} }
@ -59,5 +83,6 @@ public static class Package
socket.SendPackage(request); socket.SendPackage(request);
return socket.GetPackage(); 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());
} }