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 服务端。 internal class TcpServer { #region event /// Exception。 public Event Excepted { get; set; } /// 服务端已启动。 public Event Started { get; set; } /// 服务端已关闭。 public Event Quitted { get; set; } /// 客户端已连接。 public Event Connected { get; set; } /// 客户端已断开。 public Event Closed { get; set; } /// 已收到客户端数据。 public Event Received { get; set; } #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?.Invoke(this, new SocketEndPoint(ip, port)); } } internal void RaiseConnected(string ip, int port) { Connected?.Invoke(this, new SocketEndPoint(ip, port)); } internal void RaiseClosed(string ip, int port) { Closed?.Invoke(this, new SocketEndPoint(ip, port)); } internal void RaiseQuitted() { var quitted = Quitted; if (quitted != null) { var ip = _endpoint == null ? "" : _endpoint.Address.ToString(); var port = _endpoint == null ? 0 : _endpoint.Port; quitted(this, new SocketEndPoint(ip, port)); } } internal void RaiseReceived(string ip, int port, byte[] bytes) { Received?.Invoke(this, new SocketReceived(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 port = _port; if (port > 65535) port = 65535; if (port < 0) port = 0; return port; } set { int port = value; if (port < 0) port = 0; if (port > 65535) port = 65535; _port = port; } } /// 最大客户端数量。 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(bool inBackground = true) { 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; if (inBackground) { _listener = new Thread(Listener); _listener.IsBackground = Background; _listener.Start(); _state = _listener.IsAlive; var cep = (IPEndPoint)_socket.LocalEndPoint; _port = cep.Port; RaiseStarted(); return true; } else { _state = true; var cep = (IPEndPoint)_socket.LocalEndPoint; _port = cep.Port; RaiseStarted(); Listener(); return true; } } catch (Exception ex) { _endpoint = null; RaiseExcepted(ex); if ((_socket != null) && _socket.Connected) _socket.Close(); _state = false; Quit(); return false; } } /// 关闭服务端。 public void Quit() { Quit(true); } /// 断开与所有客户端的连接。 public void Close() { if (_client != null) { foreach (Socket socket in _client.Values) { try { var ep = (IPEndPoint)socket.RemoteEndPoint; Close(ep.Address.ToString(), ep.Port); } catch (Exception ex) { RaiseExcepted(ex); } } } } /// 断开与指定客户端的连接。 public void Close(string ip, int port) { if (port < 0) port = 0; if (port > 65535) port = 65535; if (!string.IsNullOrEmpty(ip)) { var ck = ip + "-" + port.ToString(); var cs = Client(ip, port); try { if (cs != null) cs.Close(); Remove(ck); RaiseClosed(ip, port); } catch (Exception ex) { RaiseExcepted(ex); } } } /// 向所有客户端广播数据。 public void Send(byte[] bytes) { var length = bytes.Length; if ((_client.Count > 0) && (length > 0)) { foreach (Socket i in _client.Values) Send(bytes, i); } } /// 向指定客户端发送数据。 public bool Send(byte[] bytes, string ip, int port) { if (port < 0) port = 0; if (port > 65535) port = 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 length = bytes.Length; if ((client != null) && (length > 0)) { try { return (client.Send(bytes, length, SocketFlags.None) > 0) ? true : false; } catch (Exception ex) { RaiseExcepted(ex); } } return false; } private void Listener() { while (_socket != null) { try { var socket = _socket.Accept(); if (socket != null) { var ep = (IPEndPoint)socket.RemoteEndPoint; var key = ep.Address.ToString() + "-" + ep.Port.ToString(); _client.Add(key, socket); var instance = new TcpInstance(this, _socket, socket); var thread = new Thread(instance.Process); thread.IsBackground = true; thread.Name = key; thread.Start(); RaiseConnected(ep.Address.ToString(), ep.Port); } } catch (Exception ex) { RaiseExcepted(ex); } } Quit(false); } private Socket Client(string ip, int port) { if (port < 0) port = 0; if (port > 65535) port = 65535; try { var ck = ip + "-" + port.ToString(); if (_client.ContainsKey(ck)) return (Socket)_client[ck]; } catch (Exception ex) { RaiseExcepted(ex); } return null; } #endregion } }