This commit is contained in:
2021-06-02 20:58:38 +05:00
parent c633df4ff3
commit 0250037f11
31 changed files with 204 additions and 87 deletions

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using NLog;
@@ -13,44 +14,51 @@ namespace DataClient
private Logger log = LogManager.GetCurrentClassLogger();
private Encoding enc;
private string ip = "127.0.0.1";
/// <summary>IP адрес СТП.</summary>
public string Ip
{
get { return ip; }
set
{
if (!IPAddress.TryParse(value, out _))
throw new Exception("Wrong ip address.");
else
ip = value;
}
set { ip = (IPAddress.TryParse(value, out _)) ? value : ip; }
}
private int port = 1070;
/// <summary>Порт СТП.</summary>
public int Port
{
get { return port; }
set
{
if (value < 1 && value > 65535)
throw new Exception("Wrong port.");
else
port = value;
}
set { port = (value < 1) ? 1 : (value > 65535) ? 65535 : value; }
}
private enum Code : uint
private int retryCount = 3;
/// <summary>Количество попыток переподключения.</summary>
public int RetryCount
{
check_command = 4294967295,
get { return retryCount; }
set { retryCount = value < 1 ? 1 : value; }
}
private int retryInterval = 1;
/// <summary>Время в секундах между попытками переподключения.</summary>
public int RetryInterval
{
get { return retryInterval; }
set { retryInterval = (value < 1) ? 1 : value; }
}
private TcpClient tcpC = null;
/// <summary>Коды для работы с СТП.</summary>
public enum Code : uint
{
check_command = uint.MaxValue,
version = 0,
pasp_download = 4,
download_nh = 21,
dir_browse = 23,
user_flags = 26
}
//Construction
public NETClient()
{
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
enc = Encoding.GetEncoding(866);
tcpC = new TcpClient(new IPEndPoint(IPAddress.Parse(ip), port));
}
public NETClient(string ip, int port)
{
@@ -58,21 +66,158 @@ namespace DataClient
enc = Encoding.GetEncoding(866);
Ip = ip;
Port = port;
tcpC = new TcpClient();
}
//Work with socket functions
public byte[] CreateCode(uint code, byte[] prefix = null, string val = null, byte[] postfix = null)
/// <summary>Получить неизвестное количество байт.</summary>
/// <param name="socket">Открытый сетевой поток.</param>
/// <returns>Массив байт.</returns>
private byte[] ReceiveBytesUnknown(NetworkStream ns, int awaitInterval = 1, int tryCounts = 3)
{
tryCounts = (tryCounts < 1) ? 1 : tryCounts;
awaitInterval = (awaitInterval < 1) ? 1 : awaitInterval;
var res = new List<byte>();
if (!ns.CanRead) throw new Exception("NetworkStream not access to Read.");
if (!ns.Socket.Connected) throw new Exception("NetworkStream not connected to server.");
int tryCount = 0;
do
{
if (!ns.Socket.Connected) throw new Exception("Server drop connection.");
if (!ns.DataAvailable)
{
tryCount++;
Task.Delay(awaitInterval * 1000).Wait();
continue;
}
tryCount = 0;
var buf = new byte[1024];
var length = ns.Read(buf, 0, buf.Length);
for (var i = 0; i < length; i++) res.Add(buf[i]);
} while (tryCount < tryCounts);
return res.ToArray();
}
/// <summary>Получить определенное количество байт.</summary>
/// <param name="ns">Открытый сетевой поток.</param>
/// <param name="size">Кол-во получаемый байт.</param>
/// <returns>Массив байт, равный заданному кол-ву.</returns>
private byte[] ReceiveBytesFixSize(NetworkStream ns, int size, int awaitInterval = 1, int tryCounts = 3)
{
tryCounts = (tryCounts < 1) ? 1 : tryCounts;
awaitInterval = (awaitInterval < 1) ? 1 : awaitInterval;
if (size <= 0) throw new Exception("Size can't be less or zero.");
if (!ns.CanRead) throw new Exception("NetworkStream not access to Read.");
if (!ns.Socket.Connected) throw new Exception("NetworkStream not connected to server.");
var res = new byte[size];
var countSize = 0;
int tryCount = 0;
do
{
if (!ns.Socket.Connected) throw new Exception("Server drop connection.");
if (!ns.DataAvailable)
{
tryCount++;
Task.Delay(awaitInterval * 1000).Wait();
continue;
}
tryCount = 0;
var buf = new byte[size - countSize];
var length = ns.Read(buf, 0, buf.Length);
for (var i = 0; i < length; i++) res[countSize++] = buf[i];
if (countSize == size)
return res;
} while (tryCount < tryCounts);
throw new Exception("Can't get all bytes.");
}
//Support functions
/// <summary>Формирование массива байт на отправку.</summary>
/// <param name="code">Код комманды. Конвертируется в 4 байта. (0x00 0x00 0x00 0x00)</param>
/// <param name="prefix">Байты перед передаваемой строкой.</param>
/// <param name="val">Передаваемая строка.</param>
/// <param name="postfix">Байты после передаваемой строкой.</param>
/// <returns>Массив байт для отправки на СТП.</returns>
public byte[] CreateCode(uint code, byte[] prefix = null, string val = null, byte[] postfix = null)
{
var res = new List<byte>();
res.AddRange(BitConverter.GetBytes(code));
if (prefix != null)
res.AddRange(prefix);
if(val != null)
{
res.AddRange(BitConverter.GetBytes((uint)val.Length));
res.AddRange(enc.GetBytes(val));
res.Add(0x00);
}
if (postfix != null)
res.AddRange(postfix);
return res.ToArray();
}
//Main functions
/// <summary>Открыть подключение.</summary>
/// <returns>Результат выполнения функции.</returns>
public bool Connect()
{
if (Connected()) return true;
if (tcpC == null) tcpC = new TcpClient();
try { tcpC.Connect(new IPEndPoint(IPAddress.Parse(ip), port)); }
catch { return false; }
return Connected();
}
/// <summary>Проверка подключения.</summary>
/// <returns>Возвращает состояние подключения.</returns>
public bool Connected()
{
return (tcpC != null && tcpC.Connected);
}
/// <summary>Закрыть подключение.</summary>
public void Close()
{
if (tcpC != null && !tcpC.Connected)
tcpC.Close();
}
/// <summary>Отправка массива байт на СТП.</summary>
/// <param name="send">Массив байт для отправки.</param>
public void SendBytes(byte[] send)
{
if (!Connected()) throw new Exception("Connection not exist.");
var ns = tcpC.GetStream();
if (!ns.CanWrite) throw new Exception("NetworkStream not access to Write.");
if (!ns.Socket.Connected) throw new Exception("NetworkStream not connected to server.");
ns.Write(send, 0, send.Length);
}
public byte[] ReceiveBytes()
{
var res = new List<byte>();
if (!Connected()) throw new Exception("Connection not exist.");
var ns = tcpC.GetStream();
res.AddRange(ReceiveBytesUnknown(ns));
return res.ToArray();
}
public byte[] ReceiveBytes(int size)
{
var res = new List<byte>();
if (!Connected()) throw new Exception("Connection not exist.");
var ns = tcpC.GetStream();
res.AddRange(ReceiveBytesFixSize(ns, size));
return res.ToArray();
}
/// <summary>Получение файла данных (байтами) с СТП.</summary>
/// <param name="date">Дата. Из неё формируется строка в формате YYYMMDD</param>
/// <param name="vdp">Номер печи. 00 - общецеховые параметры.</param>
/// <param name="idx">Индекс файла. От 0 до 15.</param>
/// <returns>Обработанный массив байт.</returns>
public byte[] GetFile(DateTime date, int vdp, int idx)
{
if (!Connected()) throw new Exception("Connection not exist.");
var res = new List<byte>();
var str = date.ToString("yyyyMMdd") + vdp.ToString("D2") + (idx % 16).ToString("X1");
return res.ToArray();
}
}
}