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 Event Excepted; /// 已发送数据。 public event Event Sent; /// 已接收数据。 public event Event Received; /// 已连接。 public event Event Connected; /// 已断开。 public event Event Closed; #region raise private void RaiseConnected() { if (Connected != null) Connected(this, new EventArgs()); } private void RaiseClosed() { if (Closed != null) Closed(this, new EventArgs()); } private void RaiseSent(byte[] value) { if (Sent != null) Sent(this, value); } private void RaiseReceived(byte[] value) { if (Received != null) Received(this, value); } private void RaiseExcepted(Exception value) { if (Excepted != null) Excepted(this, value); } #endregion #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 = 1000; private string _localip, _remoteip; private int _localport = 0, _remoteport = 0; private bool _background = true; /// 构造函数。 public TcpClient() { RemoteIP = "127.0.0.1"; RemotePort = 0; Timeout = 1000; } /// 构造函数。 public TcpClient(string ip, int port, int timeout = 1000) { 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 argex) { RaiseExcepted(argex); } } } /// 获取或设置远程计算机的 IP 地址。 public string RemoteIP { get { return _remoteip; } set { string vip = value; if (!NetworkUtility.IsIP(vip)) vip = NetworkUtility.Resolve(vip); if (!NetworkUtility.IsIP(vip)) vip = "127.0.0.1"; _remoteip = vip; } } /// 获取或设置远程计算机的 TCP 端口号。 public int RemotePort { get { return _remoteport; } set { int vport = value; if (vport < 0) vport = 0; if (vport > 65535) vport = 65535; _remoteport = vport; } } /// 获取或设置本地计算机的 IP 地址。 public string LocalIP { get { return _localip; } private set { _localip = string.IsNullOrEmpty(value) ? "" : value; } } /// 获取或设置本地计算机的 TCP 端口号。 public int LocalPort { get { return _localport; } private set { int vport = value; if (vport < 0) vport = 0; if (vport > 65535) vport = 65535; _localport = vport; } } /// 获取或设置超时时间。 public int Timeout { get { return _timeout; } set { _timeout = (value > 0) ? value : 1; } } /// 开始连接,并初始化发送队列。 public void Start() { Close(false); _queue = new Queue(); _provider = new Thread(Provider); _provider.IsBackground = true; _provider.Start(); // _are.WaitOne(1000); } /// 断开连接。 /// 是否引导 Closed 事件。 public void Close(bool @event = true) { CloseThread(ref _provider); CloseThread(ref _listener); CloseSocket(); CloseQueue(); _queue = null; // _are = null; if (@event) RaiseClosed(); } /// 向服务端发送数据。 /// 字节数组。 public bool Send(byte[] bytes) { if (_socket != null) { _queue.Enqueue(bytes); return true; } else { var vse = new SocketException(10057); RaiseExcepted(vse); return false; } } /// 是否已连接。 public bool Online { get { try { if (_socket != null) return _socket.Connected; } catch (Exception argex) { RaiseExcepted(argex); } return false; } } #endregion #region logic private void Listener() { var vb = new byte[TcpBuffer.Size]; var vf = 0; while (true) { try { if (_socket.Poll(50, SelectMode.SelectWrite)) { _socket.Blocking = true; vf = _socket.Receive(vb); if (vf > 0) { var vms = new MemoryStream(vb); vms.SetLength(vf); RaiseReceived(vms.ToArray()); vms.Dispose(); } else { if (_socket != null) break; } } } catch (SocketException argEx) { if (argEx.ErrorCode != 10060) RaiseExcepted(argEx); if (argEx.ErrorCode == 10054) break; } catch (Exception argEx) { RaiseExcepted(argEx); // 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(); RaiseClosed(); } private void Provider() { _break = false; _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _socket.SendTimeout = _timeout; _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 vrep = (IPEndPoint)_socket.RemoteEndPoint; var vlep = (IPEndPoint)_socket.LocalEndPoint; _remoteip = vrep.Address.ToString(); _localip = vlep.Address.ToString(); _localport = vlep.Port; RaiseConnected(); _listener = new Thread(Listener); _listener.Start(); // _are.Set(); } else { Close(); return; } } catch (Exception argEx) { RaiseExcepted(argEx); } while ((!_break) && (_socket != null)) { if (_queue.Count > 0) { var vb = _queue.Dequeue(); if (vb.Length > 0) { try { _socket.Send(vb); RaiseSent(vb); } catch (Exception argEx) { RaiseExcepted(argEx); } } else { Thread.Sleep(1); } } } } private void CloseSocket() { if (_socket != null) { try { _socket.Disconnect(false); _socket.Close(); } catch (SocketException argEx) { RaiseExcepted(argEx); } catch (Exception argEx) { RaiseExcepted(argEx); } _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 } }