using System.Threading.Tasks; namespace TLVProtocal; internal class TlvCommunicatorClient : BaseFilter, ITlvCommunicatorClient { private ITcpClient _tcpClient; private ITlvProvider _provider; private MessageQueue _messageQueue; private MessageReceiveQueue _receiveQueue; private TlvAckLayer _ackLayer; private TlvPackLayer _packLayer; private TlvContentLayer _contentLayer; private RawDataLog _dataLogLayer; private ushort _requestID = 0; private int _timeoutTimer = 0; private readonly ConcurrentDictionary _requests = []; bool ITlvCommunicatorClient.Initialize(ITlvProvider provider, bool ConvertToBigEnd, int timeoutTime) { if (this._tcpClient is not null) return false; this._tcpClient = IOFactory.GetTcpClient(); this._provider = provider; this._timeoutTimer = timeoutTime; this._ackLayer = new(ConvertToBigEnd, timeoutTime); this._packLayer = new(ConvertToBigEnd); this._contentLayer = new(ConvertToBigEnd); this._messageQueue = new(); this._messageQueue.Initialize(); this._receiveQueue = new(); this._receiveQueue.Initialize(); this._dataLogLayer = new(); string filePath = Path.Combine(Environment.CurrentDirectory, "Log", "TlvCommunicatorClient.log"); this._dataLogLayer.Initialize(filePath); _ = this >> this._contentLayer >> this._receiveQueue >> this._ackLayer >> this._packLayer >> this._messageQueue >> (BaseFilter)this._tcpClient; //this._dataLogLayer >> return true; } bool ITlvCommunicatorClient.Open(string ipAddress, ushort port) { if (this._tcpClient is null) return false; this._tcpClient.Initiallize($"TlvCommunicatorClient {ipAddress}:{port}"); return this._tcpClient.Open(ipAddress, port, out _); } bool ITlvCommunicatorClient.SendNotify(TlvData tlvData) { return base.Send(tlvData); } bool ITlvCommunicatorClient.SendRequest(TlvData request, out TlvData reply) { reply = null; SyncMessage syncMessage = new(); lock (_requests) { do request.RequestID = this.GetNextID(); while (!this._requests.TryAdd(request.RequestID.Value, syncMessage)); } Task.Factory.StartNew(() => { if (!base.Send(request)) { syncMessage.WaitEvent.Set(); this._requests.TryRemove(request.RequestID.Value, out _); } }); if (!syncMessage.WaitEvent.WaitOne(this._timeoutTimer)) { this._requests.TryRemove(request.RequestID.Value, out _); return false; } if (!this._requests.TryRemove(request.RequestID.Value, out _)) return false; reply = syncMessage.TlvData; return true; } public override bool Receive(Data data) { if (data is not TlvData tlv) return false; if (tlv.RequestID is null) { this._provider?.Received(tlv); return true; } if (!this._requests.TryGetValue(tlv.RequestID.Value, out SyncMessage syncMessage)) return false; syncMessage.TlvData = tlv; syncMessage.WaitEvent.Set(); return true; } public override bool Send(Data data) { return false; } public override void Connected(Connection connection) { if (connection is not TcpConnection tcpConnection) return; this._provider?.Connected(tcpConnection); } public override void Disconnected(Connection connection) { if (connection is not TcpConnection tcpConnection) return; this._provider?.Disconnected(tcpConnection); } private ushort GetNextID() { if (this._requestID == ushort.MaxValue) return 0; return ++_requestID; } void IDisposable.Dispose() { this._tcpClient?.Close(); this._tcpClient = null; ((IDisposable)this._messageQueue).Dispose(); this._messageQueue = null; this._packLayer = null; this._contentLayer = null; this._ackLayer = null; } } internal class SyncMessage { public TlvData TlvData { get; set; } public readonly AutoResetEvent WaitEvent = new(false); }