using Apewer; using Apewer.Internals; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace Apewer.Network { /// TCP 客户端。 public class TcpClient { #region event /// Exception。 public Event Excepted { get; set; } /// 已发送数据。 public Event Sent { get; set; } /// 已接收数据。 public Event Received { get; set; } /// 已连接。 public Event Connected { get; set; } /// 已断开。 public Event Closed { get; set; } #endregion #region definition private Thread _listener = null; private Thread _provider = null; private Socket _socket = null; private Queue _queue = null; // private AutoResetEvent _are = null; private bool _break = false; private int _timeout = 0; private string _localip, _remoteip; private int _localport = 0, _remoteport = 0; private bool _background = true; /// internal object Tag { get; set; } /// 构造函数。 public TcpClient() { RemoteIP = "127.0.0.1"; RemotePort = 0; } /// 构造函数。 public TcpClient(string ip, int port, int timeout = 0) { RemoteIP = ip; RemotePort = port; Timeout = timeout; } #endregion #region accessor /// 获取或设置监听线程是否为后台线程,默认为“是”。 public bool Background { get { return _background; } set { _background = value; try { if (_listener != null) _listener.IsBackground = value; } catch (Exception ex) { Excepted?.Invoke(this, ex); } } } /// 获取或设置远程计算机的 IP 地址。 public string RemoteIP { get { return _remoteip; } set { string ip = value; if (!NetworkUtility.IsIP(ip)) ip = NetworkUtility.Resolve(ip); if (!NetworkUtility.IsIP(ip)) ip = "127.0.0.1"; _remoteip = ip; } } /// 获取或设置远程计算机的 TCP 端口号。 public int RemotePort { get { return _remoteport; } set { int port = value; if (port < 0) port = 0; if (port > 65535) port = 65535; _remoteport = port; } } /// 获取或设置本地计算机的 IP 地址。 public string LocalIP { get { return _localip; } private set { _localip = string.IsNullOrEmpty(value) ? "" : value; } } /// 获取或设置本地计算机的 TCP 端口号。 public int LocalPort { get { return _localport; } private set { int port = value; if (port < 0) port = 0; if (port > 65535) port = 65535; _localport = port; } } /// 获取或设置超时时间。 public int Timeout { get { return _timeout; } set { _timeout = (value > 0) ? value : 0; } } /// 开始连接,并初始化发送队列。 public void Start(bool inBackground = false) { Close(false); _queue = new Queue(); if (!inBackground) { _provider = new Thread(Provider); _provider.IsBackground = true; _provider.Start(); return; } Provider(); // _are.WaitOne(1000); } /// 断开连接。 /// 是否引导 Closed 事件。 public void Close(bool @event = true) { CloseThread(ref _provider); CloseThread(ref _listener); CloseSocket(); CloseQueue(); _queue = null; // _are = null; if (@event) Closed?.Invoke(this); } /// 向服务端发送数据。 /// 字节数组。 public bool Send(byte[] bytes) { if (_socket != null) { _queue.Enqueue(bytes); return true; } else { var ex = new SocketException(10057); Excepted?.Invoke(this, ex); return false; } } /// 是否已连接。 public bool Online { get { try { if (_socket != null) return _socket.Connected; } catch (Exception ex) { Excepted?.Invoke(this, ex); } return false; } } #endregion #region logic private void Listener() { var buffer = new byte[TcpBuffer.Size]; var length = 0; while (true) { try { if (_socket.Poll(50, SelectMode.SelectWrite)) { _socket.Blocking = true; length = _socket.Receive(buffer); if (length > 0) { var bytes = new byte[length]; Array.Copy(buffer, bytes, length); Received?.Invoke(this, bytes); } else { if (_socket != null) break; } } } catch (SocketException ex) { if (ex.ErrorCode != 10060) Excepted?.Invoke(this, ex); if (ex.ErrorCode == 10054) break; } catch (Exception ex) { Excepted?.Invoke(this, ex); // break; } } if (_provider != null) { if (_provider.IsAlive) _provider.Abort(); _provider = null; } if (_socket != null) { _socket.Disconnect(true); _socket.Close(); _socket = null; } CloseThread(ref _provider); CloseSocket(); CloseQueue(); Closed?.Invoke(this); } private void Provider() { _break = false; _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); if (_timeout > 0) _socket.SendTimeout = _timeout; if (_timeout > 0) _socket.ReceiveTimeout = _timeout; //_are = new AutoResetEvent(false); try { _socket.Blocking = true; _socket.Connect(_remoteip, _remoteport); if (_socket.Connected) { _socket.SendBufferSize = TcpBuffer.Size; _socket.ReceiveBufferSize = TcpBuffer.Size; var rep = (IPEndPoint)_socket.RemoteEndPoint; var lep = (IPEndPoint)_socket.LocalEndPoint; _remoteip = rep.Address.ToString(); _localip = lep.Address.ToString(); _localport = lep.Port; Connected?.Invoke(this); _listener = new Thread(Listener); _listener.Start(); // _are.Set(); } else { Close(); return; } } catch (Exception ex) { Excepted?.Invoke(this, ex); } while ((!_break) && (_socket != null)) { if (_queue.Count > 0) { var bytes = _queue.Dequeue(); if (bytes.Length > 0) { try { _socket.Send(bytes); Sent?.Invoke(this, bytes); } catch (Exception ex) { Excepted?.Invoke(this, ex); } } else { Thread.Sleep(1); } } } } private void CloseSocket() { if (_socket != null) { try { _socket.Disconnect(false); _socket.Close(); } catch (SocketException ex) { Excepted?.Invoke(this, ex); } catch (Exception ex) { Excepted?.Invoke(this, ex); } _socket = null; } } private void CloseThread(ref Thread thread) { if (thread != null) { if (thread.IsAlive) thread.Abort(); thread = null; } } private void CloseQueue() { if (_queue != null) _queue.Clear(); } #endregion } }