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
}
}