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();
- }
- }
|