|
|
|
|
using System.Net;
|
|
|
|
|
using ZeroLevel;
|
|
|
|
|
using ZeroLevel.Network;
|
|
|
|
|
using ZeroLevel.Services.HashFunctions;
|
|
|
|
|
using ZeroLevel.Services.Serialization;
|
|
|
|
|
|
|
|
|
|
namespace Client
|
|
|
|
|
{
|
|
|
|
|
public class Info
|
|
|
|
|
: IBinarySerializable
|
|
|
|
|
{
|
|
|
|
|
public uint Id;
|
|
|
|
|
public uint Length;
|
|
|
|
|
public uint Checksum;
|
|
|
|
|
|
|
|
|
|
public void Deserialize(IBinaryReader reader)
|
|
|
|
|
{
|
|
|
|
|
this.Id = reader.ReadUInt32();
|
|
|
|
|
this.Length = reader.ReadUInt32();
|
|
|
|
|
this.Checksum = reader.ReadUInt32();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Serialize(IBinaryWriter writer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteUInt32(this.Id);
|
|
|
|
|
writer.WriteUInt32(this.Length);
|
|
|
|
|
writer.WriteUInt32(this.Checksum);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public class Fragment
|
|
|
|
|
: IBinarySerializable
|
|
|
|
|
{
|
|
|
|
|
public uint Id;
|
|
|
|
|
public uint Offset;
|
|
|
|
|
public uint Checksum;
|
|
|
|
|
public byte[] Payload;
|
|
|
|
|
|
|
|
|
|
public void Deserialize(IBinaryReader reader)
|
|
|
|
|
{
|
|
|
|
|
this.Id = reader.ReadUInt32();
|
|
|
|
|
this.Offset = reader.ReadUInt32();
|
|
|
|
|
this.Checksum = reader.ReadUInt32();
|
|
|
|
|
this.Payload = reader.ReadBytes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Serialize(IBinaryWriter writer)
|
|
|
|
|
{
|
|
|
|
|
writer.WriteUInt32(this.Id);
|
|
|
|
|
writer.WriteUInt32(this.Offset);
|
|
|
|
|
writer.WriteUInt32(this.Checksum);
|
|
|
|
|
writer.WriteBytes(this.Payload);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class Program
|
|
|
|
|
{
|
|
|
|
|
private readonly static XXHashUnsafe _hash = new XXHashUnsafe(667);
|
|
|
|
|
|
|
|
|
|
private static long _successSend = 0;
|
|
|
|
|
private static long _faultSend = 0;
|
|
|
|
|
|
|
|
|
|
static void Main(string[] args)
|
|
|
|
|
{
|
|
|
|
|
Log.AddConsoleLogger();
|
|
|
|
|
var ex = Bootstrap.CreateExchange();
|
|
|
|
|
var address = ReadIP();
|
|
|
|
|
var port = ReadPort();
|
|
|
|
|
ex.RoutesStorage.Set("server", new IPEndPoint(address, port));
|
|
|
|
|
|
|
|
|
|
Sheduller.RemindEvery(TimeSpan.FromMilliseconds(300), () =>
|
|
|
|
|
{
|
|
|
|
|
Console.SetCursorPosition(0, 0);
|
|
|
|
|
Console.WriteLine($"Success/Fault network: {_successSend} / {_faultSend}");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
uint index = 0;
|
|
|
|
|
while (true)
|
|
|
|
|
{
|
|
|
|
|
if (Console.KeyAvailable)
|
|
|
|
|
{
|
|
|
|
|
switch (Console.ReadKey().Key)
|
|
|
|
|
{
|
|
|
|
|
case ConsoleKey.Escape:
|
|
|
|
|
ex?.Dispose();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (index % 2 == 0)
|
|
|
|
|
{
|
|
|
|
|
SendDataEqParts(ex, index, 1024 + index * 3 + 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
SendDataDiffParts(ex.GetConnection("server"), index, 1024 + index * 3 + 1);
|
|
|
|
|
}
|
|
|
|
|
index++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void SendDataDiffParts(IClient client, uint id, uint length)
|
|
|
|
|
{
|
|
|
|
|
var payload = GetByteArray(length);
|
|
|
|
|
var full_checksum = _hash.Hash(payload);
|
|
|
|
|
var info = new Info { Checksum = full_checksum, Id = id, Length = length };
|
|
|
|
|
if (client.Request<Info, bool>("start", info, res =>
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _successSend);
|
|
|
|
|
}))
|
|
|
|
|
{
|
|
|
|
|
uint size = 1;
|
|
|
|
|
uint offset = 0;
|
|
|
|
|
while (offset < payload.Length)
|
|
|
|
|
{
|
|
|
|
|
var fragment = GetFragment(id, payload, offset, size);
|
|
|
|
|
if (!client.Request<Fragment, bool>("part", fragment, res =>
|
|
|
|
|
{
|
|
|
|
|
if (!res)
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _faultSend);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _successSend);
|
|
|
|
|
}
|
|
|
|
|
}))
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _faultSend);
|
|
|
|
|
}
|
|
|
|
|
offset += size;
|
|
|
|
|
size += 1;
|
|
|
|
|
}
|
|
|
|
|
client.Send<uint>("complete", id);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _faultSend);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void SendDataEqParts(IExchange exchange, uint id, uint length)
|
|
|
|
|
{
|
|
|
|
|
var payload = GetByteArray(length);
|
|
|
|
|
var full_checksum = _hash.Hash(payload);
|
|
|
|
|
var info = new Info { Checksum = full_checksum, Id = id, Length = length };
|
|
|
|
|
if (exchange.Request<Info, bool>("server", "start", info))
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _successSend);
|
|
|
|
|
uint size = 4096;
|
|
|
|
|
uint offset = 0;
|
|
|
|
|
while (offset < payload.Length)
|
|
|
|
|
{
|
|
|
|
|
var fragment = GetFragment(id, payload, offset, size);
|
|
|
|
|
if (!exchange.Request<Fragment, bool>("server", "part", fragment))
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _faultSend);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _successSend);
|
|
|
|
|
}
|
|
|
|
|
offset += size;
|
|
|
|
|
}
|
|
|
|
|
exchange.Send<uint>("server", "complete", id);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Interlocked.Increment(ref _faultSend);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static Fragment GetFragment(uint id, byte[] data, uint offset, uint size)
|
|
|
|
|
{
|
|
|
|
|
int diff = (int)(-(data.Length - (offset + size)));
|
|
|
|
|
if (diff > 0)
|
|
|
|
|
{
|
|
|
|
|
size -= (uint)diff;
|
|
|
|
|
}
|
|
|
|
|
var payload = new byte[size];
|
|
|
|
|
Array.Copy(data, offset, payload, 0, size);
|
|
|
|
|
var ch = _hash.Hash(payload);
|
|
|
|
|
return new Fragment
|
|
|
|
|
{
|
|
|
|
|
Id = id,
|
|
|
|
|
Checksum = ch,
|
|
|
|
|
Offset = offset,
|
|
|
|
|
Payload = payload
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static byte[] GetByteArray(uint size)
|
|
|
|
|
{
|
|
|
|
|
Random rnd = new Random();
|
|
|
|
|
Byte[] b = new Byte[size];
|
|
|
|
|
rnd.NextBytes(b);
|
|
|
|
|
return b;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static IPAddress ReadIP()
|
|
|
|
|
{
|
|
|
|
|
IPAddress ip = null;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("IP>");
|
|
|
|
|
var address = Console.ReadLine();
|
|
|
|
|
if (IPAddress.TryParse(address, out ip) == false)
|
|
|
|
|
{
|
|
|
|
|
ip = null;
|
|
|
|
|
Console.WriteLine($"Incorrect ip address '{address}'");
|
|
|
|
|
}
|
|
|
|
|
} while (ip == null);
|
|
|
|
|
return ip;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int ReadPort()
|
|
|
|
|
{
|
|
|
|
|
int port = -1;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
Console.WriteLine("PORT>");
|
|
|
|
|
var port_line = Console.ReadLine();
|
|
|
|
|
if (int.TryParse(port_line, out port) == false || port <= 0)
|
|
|
|
|
{
|
|
|
|
|
port = -1;
|
|
|
|
|
Console.WriteLine($"Incorrect port '{port_line}'");
|
|
|
|
|
}
|
|
|
|
|
} while (port <= 0);
|
|
|
|
|
return port;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|