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