|
|
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>
public class TcpServer {
#region event
/// <summary>Exception。</summary>
public event Event<Exception> Excepted;
/// <summary>服务端已启动。</summary>
public event SocketEndPointEventHandler Started;
/// <summary>服务端已关闭。</summary>
public event SocketEndPointEventHandler Quitted;
/// <summary>客户端已连接。</summary>
public event SocketEndPointEventHandler Connected;
/// <summary>客户端已断开。</summary>
public event SocketEndPointEventHandler Closed;
/// <summary>已收到客户端数据。</summary>
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;
/// <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 argex) { RaiseExcepted(argex); } } }
/// <summary>端口。</summary>
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; } }
/// <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() { 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 argex) { _endpoint = null; RaiseExcepted(argex); if ((_socket != null) && _socket.Connected) _socket.Close(); Quit(); return false; } }
/// <summary>关闭服务端。</summary>
public void Quit() { Quit(true); }
/// <summary>断开与所有客户端的连接。</summary>
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 argex) { RaiseExcepted(argex); } } } }
/// <summary>断开与指定客户端的连接。</summary>
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 argex) { RaiseExcepted(argex); } } }
/// <summary>向所有客户端广播数据。</summary>
public void Send(byte[] bytes) { var vl = bytes.Length; if ((_client.Count > 0) && (vl > 0)) { foreach (Socket i in _client.Values) Send(bytes, i); } }
/// <summary>向指定客户端发送数据。</summary>
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
/// <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 argex) { RaiseExcepted(argex); } } }
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 argex) { RaiseExcepted(argex); } } } }
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 argex) { RaiseExcepted(argex); } } 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 argex) { RaiseExcepted(argex); } } 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 argex) { RaiseExcepted(argex); } return null; }
#endregion
} }
|