using System; using System.Collections; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; using System.IO; using Apewer.Internals; using Apewer; namespace Apewer.Network { /// TCP 服务端。 public class TcpServer { #region event /// Exception。 public event Event Excepted; /// 服务端已启动。 public event SocketEndPointEventHandler Started; /// 服务端已关闭。 public event SocketEndPointEventHandler Quitted; /// 客户端已连接。 public event SocketEndPointEventHandler Connected; /// 客户端已断开。 public event SocketEndPointEventHandler Closed; /// 已收到客户端数据。 public event SocketReceivedEventHandler Received; #region raise internal void RaiseExcepted(Exception exception) { if (Excepted != null) Excepted(this, exception); } internal void RaiseStarted() { if (Started != null) { var ip = _endpoint == null ? "" : _endpoint.Address.ToString(); var port = _endpoint == null ? 0 : _endpoint.Port; Started(this, ip, port); } } internal void RaiseConnected(string ip, int port) { if (Connected != null) Connected(this, ip, port); } internal void RaiseClosed(string ip, int port) { if (Closed != null) Closed(this, ip, port); } internal void RaiseQuitted() { if (Quitted != null) { var ip = _endpoint == null ? "" : _endpoint.Address.ToString(); var port = _endpoint == null ? 0 : _endpoint.Port; Quitted(this, ip, port); } } internal void RaiseReceived(string ip, int port, byte[] bytes) { if (Received != null) Received(this, ip, port, bytes); } #endregion #endregion #region definition private Socket _socket = null; private Thread _listener = null; private SortedList _client = null; private IPEndPoint _endpoint = null; private int _port = 0; private int _max = 0; private int _timeout = 0; private bool _state = false; private bool _background = true; /// 构造函数。 public TcpServer(int port = 0) { Port = port; Max = 1000; Timeout = 1000; } #endregion #region accessor /// 获取或设置监听线程是否为后台线程,默认为“是”。 public bool Background { get { return _background; } set { _background = value; try { if (_listener != null) _listener.IsBackground = value; } catch (Exception ex) { RaiseExcepted(ex); } } } /// 端口。 public int Port { get { int vr = _port; if (vr > 65535) vr = 65535; if (vr < 0) vr = 0; return vr; } set { int vport = value; if (vport < 0) vport = 0; if (vport > 65535) vport = 65535; _port = vport; } } /// 最大客户端数量。 public int Max { get { return _max; } set { _max = (value > 0) ? value : 0; } } /// 发送数据和接收数据的超时时间。 public int Timeout { get { return _timeout; } set { _timeout = (value > 0) ? value : 0; } } /// 服务端正在运行。 public bool Alive { get { return (_listener != null) ? _listener.IsAlive : false; } } /// 已连接的客户端数量。 public int Count { get { return (_client != null) ? _client.Count : 0; } } /// 启动服务端。 public bool Start() { try { _endpoint = new IPEndPoint(IPAddress.Any, Port); _client = new SortedList(); _socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _socket.Bind(_endpoint); _socket.Listen(Max); _socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.AcceptConnection, 1); _socket.ReceiveTimeout = Timeout; _socket.SendTimeout = Timeout; _listener = new Thread(Listener); _listener.IsBackground = Background; _listener.Start(); _state = _listener.IsAlive; var vcep = (IPEndPoint)_socket.LocalEndPoint; _port = vcep.Port; RaiseStarted(); return true; } catch (Exception ex) { _endpoint = null; RaiseExcepted(ex); if ((_socket != null) && _socket.Connected) _socket.Close(); Quit(); return false; } } /// 关闭服务端。 public void Quit() { Quit(true); } /// 断开与所有客户端的连接。 public void Close() { if (_client != null) { foreach (Socket vcs in _client.Values) { try { var vep = (IPEndPoint)vcs.RemoteEndPoint; Close(vep.Address.ToString(), vep.Port); } catch (Exception ex) { RaiseExcepted(ex); } } } } /// 断开与指定客户端的连接。 public void Close(string ip, int port) { int vport = port; if (vport < 0) vport = 0; if (vport > 65535) vport = 65535; if (!string.IsNullOrEmpty(ip)) { var vck = ip + ":" + vport.ToString(); var vcs = Client(ip, vport); try { if (vcs != null) vcs.Close(); Remove(vck); RaiseClosed(ip, vport); } catch (Exception ex) { RaiseExcepted(ex); } } } /// 向所有客户端广播数据。 public void Send(byte[] bytes) { var vl = bytes.Length; if ((_client.Count > 0) && (vl > 0)) { foreach (Socket i in _client.Values) Send(bytes, i); } } /// 向指定客户端发送数据。 public bool Send(byte[] bytes, string ip, int port) { int vport = port; if (vport < 0) vport = 0; if (vport > 65535) vport = 65535; if (string.IsNullOrEmpty(ip)) return false; return Send(bytes, Client(ip, port)); } #endregion #region logic /// /// /// /// private void Quit(bool @event) { Close(); if (_listener != null) { if (_listener.IsAlive) _listener.Abort(); _listener = null; } if (_socket != null) { _socket.Close(); _socket = null; } if (_client != null) { _client.Clear(); _client = null; } _endpoint = null; if (@event) RaiseQuitted(); } private void Close(Socket socket) { if (socket != null) { try { socket.Close(); } catch (Exception ex) { RaiseExcepted(ex); } } } internal void Remove(string key) { if ((_client != null) && (!string.IsNullOrEmpty(key))) { if (_client.ContainsKey(key)) { try { Close((Socket)_client[key]); _client.Remove(key); } catch (Exception ex) { RaiseExcepted(ex); } } } } private bool Send(byte[] bytes, Socket client) { var vl = bytes.Length; if ((client != null) && (vl > 0)) { try { return (client.Send(bytes, vl, SocketFlags.None) > 0) ? true : false; } catch (Exception ex) { RaiseExcepted(ex); } } return false; } private void Listener() { while (_socket != null) { try { var vcs = _socket.Accept(); if (vcs != null) { var vep = (IPEndPoint)vcs.RemoteEndPoint; var vck = vep.Address.ToString() + ":" + vep.Port.ToString(); _client.Add(vck, vcs); var vci = new TcpInstance(this, _socket, vcs); var vct = new Thread(vci.Process); vct.IsBackground = true; vct.Name = vck; vct.Start(); RaiseConnected(vep.Address.ToString(), vep.Port); } } catch (Exception ex) { RaiseExcepted(ex); } } Quit(false); } private Socket Client(string ip, int port) { int vport = port; if (vport < 0) vport = 0; if (vport > 65535) vport = 65535; try { var vck = ip + ":" + vport.ToString(); if (_client.ContainsKey(vck)) return (Socket)_client[vck]; } catch (Exception ex) { RaiseExcepted(ex); } return null; } #endregion } }