using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
namespace IStation
{
///
/// TcpListener实现异步TCP服务器
///
public class AsyncTcpServer: IDisposable
{
#region 私有字段
private readonly object _obj = new object();//lock对象
private TcpListener _listener;//服务器使用的异步TcpListener
private List _tcpClientStates;//客户端会话列表
private bool _disposed = false;//是否已经释放
#endregion
#region 属性
///
/// 服务器是否正在运行
///
public bool IsRunning { get; private set; }
///
/// 监听的IP地址
///
public IPAddress Address { get; private set; }
///
/// 监听的端口
///
public int Port { get; private set; }
#endregion
#region 构造函数
///
/// 异步TCP服务器
///
/// 监听的IP地址
/// 监听的端口
public AsyncTcpServer(IPAddress ipAddress, int port)
{
this.Address = ipAddress;
this.Port = port;
_tcpClientStates = new List();
_listener = new TcpListener(Address, Port);
_listener.AllowNatTraversal(true);
}
#endregion
#region Method
///
/// 启动服务器
///
public void Start()
{
if (!this.IsRunning)
{
this.IsRunning = true;
_listener.Start();
_listener.BeginAcceptTcpClient(
new AsyncCallback(HandleTcpClientAccepted), _listener);
}
}
///
/// 启动服务器
///
///
/// 服务器所允许的挂起连接序列的最大长度
///
public void Start(int backlog)
{
if (!this.IsRunning)
{
this.IsRunning = true;
_listener.Start(backlog);
_listener.BeginAcceptTcpClient(
new AsyncCallback(HandleTcpClientAccepted), _listener);
}
}
///
/// 停止服务器
///
public void Stop()
{
if (IsRunning)
{
IsRunning = false;
_listener.Stop();
lock (_obj)
{
//关闭所有客户端连接
_tcpClientStates.ForEach(x=>x.Close());
_tcpClientStates.Clear();
}
}
}
///
/// 处理客户端连接的函数
///
///
private void HandleTcpClientAccepted(IAsyncResult ar)
{
if (IsRunning)
{
//TcpListener tcpListener = (TcpListener)ar.AsyncState;
var client = _listener.EndAcceptTcpClient(ar);
var buffer = new byte[client.ReceiveBufferSize];
var state = new TcpClientState(client,buffer);
lock (_obj)
{
_tcpClientStates.Add(state);
RaiseClientConnected(state);
}
NetworkStream stream = state.NetworkStream;
//开始异步读取数据
stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
_listener.BeginAcceptTcpClient(
new AsyncCallback(HandleTcpClientAccepted), ar.AsyncState);
}
}
///
/// 数据接收回调函数
///
///
private void HandleDataReceived(IAsyncResult ar)
{
if (IsRunning)
{
var state = (TcpClientState)ar.AsyncState;
var stream = state.NetworkStream;
int recv = 0;
try
{
recv = stream.EndRead(ar);
}
catch
{
recv = 0;
}
if (recv == 0)
{
// connection has been closed
lock (_obj)
{
_tcpClientStates.Remove(state);
//触发客户端连接断开事件
RaiseClientDisconnected(state);
return;
}
}
// received byte and trigger event notification
byte[] buff = new byte[recv];
Buffer.BlockCopy(state.Buffer, 0, buff, 0, recv);
//触发数据收到事件
RaiseDataReceived(state,buff);
// continue listening for tcp datagram packets
stream.BeginRead(state.Buffer, 0, state.Buffer.Length, HandleDataReceived, state);
}
}
///
/// 发送数据
///
/// 接收数据的客户端会话
/// 数据报文
public void Send(TcpClientState state, byte[] data)
{
if (!IsRunning)
return;
state.NetworkStream.BeginWrite(data, 0, data.Length, SendDataEnd, state.TcpClient);
}
///
/// 发送数据完成处理函数
///
/// 目标客户端Socket
private void SendDataEnd(IAsyncResult ar)
{
((TcpClient)ar.AsyncState).GetStream().EndWrite(ar);
}
#endregion
#region 事件
///
/// 与客户端的连接已建立事件
///
public event EventHandler TcpClientConnected;
///
/// 与客户端的连接已断开事件
///
public event EventHandler TcpClientDisconnected;
///
/// 接收到数据事件
///
public event Action DataReceived;
///
/// 触发客户端连接事件
///
///
private void RaiseClientConnected(TcpClientState state)
{
if(this.TcpClientConnected!=null)
this.TcpClientConnected(this, new AsyncTcpEventArgs(state));
}
///
/// 触发客户端连接断开事件
///
///
private void RaiseClientDisconnected(TcpClientState state)
{
if(this.TcpClientDisconnected!=null)
this.TcpClientDisconnected(this, new AsyncTcpEventArgs(state));
}
///
/// 触发接收到数据报文事件
///
///
private void RaiseDataReceived(TcpClientState state,byte[] bytes)
{
if(this.DataReceived!=null)
this.DataReceived(state,bytes);
}
#endregion
#region 释放
///
/// Performs application-defined tasks associated with freeing,
/// releasing, or resetting unmanaged resources.
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources
///
/// true to release
/// both managed and unmanaged resources; false
/// to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
{
if (!this._disposed)
{
if (disposing)
{
try
{
Stop();
if (_listener != null)
{
_listener = null;
}
}
catch //(SocketException ex)
{
//TODO
//throw ex;
}
}
_disposed = true;
}
}
#endregion
}
}