|
|
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 {
/// <summary>TCP 服务端。</summary>
internal class TcpServer {
#region event
/// <summary>Exception。</summary>
public Event<Exception> Excepted { get; set; }
/// <summary>服务端已启动。</summary>
public Event<SocketEndPoint> Started { get; set; }
/// <summary>服务端已关闭。</summary>
public Event<SocketEndPoint> Quitted { get; set; }
/// <summary>客户端已连接。</summary>
public Event<SocketEndPoint> Connected { get; set; }
/// <summary>客户端已断开。</summary>
public Event<SocketEndPoint> Closed { get; set; }
/// <summary>已收到客户端数据。</summary>
public Event<SocketReceived> 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;
/// <summary>构造函数。</summary>
public TcpServer(int port = 0) { Port = port; Max = 1000; Timeout = 1000; }
#endregion
#region accessor
/// <summary>获取或设置监听线程是否为后台线程,默认为“是”。</summary>
public bool Background { get { return _background; } set { _background = value; try { if (_listener != null) _listener.IsBackground = value; } catch (Exception ex) { RaiseExcepted(ex); } } }
/// <summary>端口。</summary>
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; } }
/// <summary>最大客户端数量。</summary>
public int Max { get { return _max; } set { _max = (value > 0) ? value : 0; } }
/// <summary>发送数据和接收数据的超时时间。</summary>
public int Timeout { get { return _timeout; } set { _timeout = (value > 0) ? value : 0; } }
/// <summary>服务端正在运行。</summary>
public bool Alive { get { return (_listener != null) ? _listener.IsAlive : false; } }
/// <summary>已连接的客户端数量。</summary>
public int Count { get { return (_client != null) ? _client.Count : 0; } }
/// <summary>启动服务端。</summary>
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; } }
/// <summary>关闭服务端。</summary>
public void Quit() { Quit(true); }
/// <summary>断开与所有客户端的连接。</summary>
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); } } } }
/// <summary>断开与指定客户端的连接。</summary>
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); } } }
/// <summary>向所有客户端广播数据。</summary>
public void Send(byte[] bytes) { var length = bytes.Length; if ((_client.Count > 0) && (length > 0)) { foreach (Socket i in _client.Values) Send(bytes, i); } }
/// <summary>向指定客户端发送数据。</summary>
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
/// <summary>
///
/// </summary>
/// <param name="event"></param>
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
} }
|