114 lines
2.5 KiB
C#
114 lines
2.5 KiB
C#
using System.Net.Sockets;
|
|
|
|
namespace InnovEnergy.Lib.Channels.V2;
|
|
|
|
public class TcpChannel : IChannel<IReadOnlyList<Byte>>
|
|
{
|
|
private Int32 TimeoutMs { get; }
|
|
private String Hostname { get; }
|
|
private UInt16 Port { get; }
|
|
private Byte[] Buffer { get; }
|
|
|
|
private Socket? Socket { get; set; }
|
|
|
|
public TcpChannel(String hostname,
|
|
UInt16 port,
|
|
TimeSpan timeout = default,
|
|
Int32 bufferSize = 8192)
|
|
{
|
|
if (bufferSize <= 0)
|
|
throw new ArgumentOutOfRangeException(nameof(bufferSize));
|
|
|
|
Hostname = hostname;
|
|
Port = port;
|
|
TimeoutMs = (Int32)timeout.TotalMilliseconds;
|
|
Buffer = new Byte[bufferSize];
|
|
}
|
|
|
|
|
|
public async Task<IReadOnlyList<Byte>> Read()
|
|
{
|
|
try
|
|
{
|
|
await Open();
|
|
|
|
var nRead = await Socket!.ReceiveAsync(Buffer, SocketFlags.None);
|
|
|
|
if (nRead <= 0)
|
|
throw new Exception("TCP Connection was closed");
|
|
|
|
// copy from buffer, so we can reuse it
|
|
var data = new Byte[nRead];
|
|
Array.Copy(Buffer, data, nRead);
|
|
return data;
|
|
}
|
|
catch
|
|
{
|
|
Close();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private async Task Open()
|
|
{
|
|
if (Socket is not null)
|
|
return;
|
|
|
|
Socket = new Socket(SocketType.Stream, ProtocolType.Tcp)
|
|
{
|
|
Blocking = true,
|
|
NoDelay = true,
|
|
LingerState = new LingerOption(false, 0),
|
|
ReceiveBufferSize = Buffer.Length,
|
|
SendBufferSize = Buffer.Length,
|
|
ReceiveTimeout = TimeoutMs,
|
|
SendTimeout = TimeoutMs,
|
|
};
|
|
|
|
var cts = new CancellationTokenSource();
|
|
cts.CancelAfter(TimeoutMs);
|
|
|
|
try
|
|
{
|
|
await Socket.ConnectAsync(Hostname, Port, cts.Token).AsTask();
|
|
}
|
|
catch
|
|
{
|
|
Socket = null!;
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task Write(IReadOnlyList<Byte> tx)
|
|
{
|
|
try
|
|
{
|
|
await Open();
|
|
await Socket!.SendAsync(tx as Byte[] ?? tx.ToArray(), SocketFlags.None);
|
|
}
|
|
catch
|
|
{
|
|
Close();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private void Close()
|
|
{
|
|
if (Socket is null)
|
|
return;
|
|
|
|
try
|
|
{
|
|
Socket.Dispose();
|
|
}
|
|
finally
|
|
{
|
|
Socket = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|