| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | namespace Universal.IO;internal class IOTcpClient : BaseFilter, ITcpClient{    #region Internal Variables    public string? Name { get; internal set; }    bool _bInitialize = false;    volatile bool _bOpen = false;    System.Net.Sockets.TcpClient? _tcpClient = null;    Task? _readTask = null;    TcpConnection? _tcpConnection = null;    #endregion    bool ITcpClient.Initiallize(string name)    {        lock (this)        {            if (_bInitialize)                return false;            this._bInitialize = true;            this.Name = name;            return true;        }    }    bool ITcpClient.Open(string remoteHost, ushort remotePort, out TcpConnection? tcpConnection, string? localHost, ushort localPort, bool noDelay, int timeout, int receiveBufferSize)    {        tcpConnection = null;        lock (this)        {            if (!_bInitialize)                return false;            if (_bOpen)                return false;            if (!IPAddress.TryParse(remoteHost, out IPAddress? remoteIPAddress) || remoteIPAddress is null)                return false;            AutoResetEvent? allowOpenEvent = new(false);            bool result = false;            try            {                _tcpClient = new() { NoDelay = noDelay };                if (string.IsNullOrEmpty(localHost) || !IPAddress.TryParse(localHost, out IPAddress? localIP) || localIP is null)                {                    _tcpClient = new() { NoDelay = noDelay };                }                else                {                    IPEndPoint localEP = new(localIP, localPort);                    _tcpClient = new(localEP) { NoDelay = noDelay };                }                using CancellationTokenSource cancellationTokenSource = new();                Task valueTask = _tcpClient.ConnectAsync(remoteIPAddress, remotePort);                if (!valueTask.Wait(timeout))                {                    cancellationTokenSource.Cancel();                    return false;                }                TcpConnection? connection = default;                _readTask = Task.Factory.StartNew(async () =>                {                    try                    {                        if (_tcpClient.Client.LocalEndPoint is not IPEndPoint || _tcpClient.Client.RemoteEndPoint is not IPEndPoint)                            return;                        connection = new((IPEndPoint)_tcpClient.Client.LocalEndPoint, (IPEndPoint)_tcpClient.Client.RemoteEndPoint, null!);                        _tcpConnection = connection;                        NetworkStream networkStream = _tcpClient.GetStream();                        Thread.Sleep(0);                        try                        {                            _bOpen = true;                            base.PrevConnector?.Connected(connection);                            result = true;                        }                        finally { allowOpenEvent.Set(); }                        for (byte[] buffer = new byte[receiveBufferSize]; ;)                        {                            int bytesRead = 0;                            DateTime receiveTime;                            try                            {                                bytesRead = await networkStream.ReadAsync(buffer);                                receiveTime = DateTime.Now;                            }                            catch                            {                                break;                            }                            if (bytesRead <= 0)                                break;                            byte[] cache = new byte[bytesRead];                            Array.Copy(buffer, cache, bytesRead);                            Data receivedData = new(cache, connection, receiveTime);                            try { base.PrevReceiver?.Receive(receivedData); } catch { }                        }                        try { _tcpClient?.Close(); } catch { }                        try { base.PrevConnector?.Disconnected(connection); } catch { }                        _tcpClient = null;                        _bOpen = false;                    }                    catch { }                }, TaskCreationOptions.LongRunning);            }            catch            {                _tcpClient = null;                return false;            }            allowOpenEvent.WaitOne();            tcpConnection = _tcpConnection;            if (result)                return true;            _tcpClient = null;            return false;        }    }    bool ITcpClient.Close()    {        lock (this)        {            if (!_bInitialize)                return false;            if (!_bOpen)                return true;            try { _tcpClient?.Close(); } catch { }            _readTask?.Wait();            _readTask = null;            _bOpen = false;            return true;        }    }    public override bool Send(Data data)    {        if (!_bInitialize)            return false;        if (!_bOpen)            return false;        if (_tcpClient?.Connected != true)            return false;        if (data.RawData is null || data.RawData.Length == 0)            return false;        try        {            NetworkStream networkStream = _tcpClient!.GetStream();            networkStream.Write([.. data.RawData], 0, data.RawData.Length);            networkStream.Flush();            data.DateTime = DateTime.Now;        }        catch        {            return false;        }        return true;    }    void IDisposable.Dispose()    {        (this as ITcpClient).Close();    }}
 |