FSP simplified
This commit is contained in:
parent
9d48b41e30
commit
0275ef1bb1
@ -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>
|
||||||
|
|||||||
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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());
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user