本文引见
TcpListener 类供应一些简朴要领,用于在阻挠同步形式下侦听和吸收传入衔接要求。 可运用 TcpClient 或 Socket 来衔接 TcpListener。 可运用 IPEndPoint、当地 IP 地点及端口号或许仅运用端口号,来竖立 TcpListener。 能够将当地 IP 地点指定为 Any,将当地端口号指定为 0(假如愿望基本效劳供应顺序为您分派这些值)。 假如您挑选如许做,可在衔接套接字后运用 LocalEndpoint 属性来标识已指定的信息。运用 Start 要领,可最先侦听传入的衔接要求。 Start 将对传入衔接举行列队,直至您挪用 Stop 要领或它已完成 MaxConnections 列队为止。 可运用 AcceptSocket 或 AcceptTcpClient 从传入衔接要求行列提取衔接。 这两种要领将阻挠。 假如要防止阻挠,可起首运用 Pending 要领来肯定行列中是不是有可用的衔接要求。
虽然TcpListener已封装的比较不错了,我们于是就运用它在组织一个比较不错的异步TCP效劳器,这里依旧和前两章一样,给出效劳器中的代码,代码中解释很细致,我也会给出相干的封装类。
TcpListener异步TCP效劳器
效劳器代码
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; namespace NetFrame.Net.TCP.Listener.Asynchronous { /// <summary> /// TcpListener完成异步TCP效劳器 /// </summary> public class AsyncTCPServer : IDisposable { #region Fields /// <summary> /// 效劳器顺序许可的最大客户端衔接数 /// </summary> private int _maxClient; /// <summary> /// 当前的衔接的客户端数 /// </summary> private int _clientCount; /// <summary> /// 效劳器运用的异步TcpListener /// </summary> private TcpListener _listener; /// <summary> /// 客户端会话列表 /// </summary> private List<Object> _clients; private bool disposed = false; #endregion #region Properties /// <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; } /// <summary> /// 通讯运用的编码 /// </summary> public Encoding Encoding { get; set; } #endregion #region 组织函数 /// <summary> /// 异步TCP效劳器 /// </summary> /// <param name="listenPort">监听的端口</param> public AsyncTCPServer(int listenPort) : this(IPAddress.Any, listenPort) { } /// <summary> /// 异步TCP效劳器 /// </summary> /// <param name="localEP">监听的终结点</param> public AsyncTCPServer(IPEndPoint localEP) : this(localEP.Address, localEP.Port) { } /// <summary> /// 异步TCP效劳器 /// </summary> /// <param name="localIPAddress">监听的IP地点</param> /// <param name="listenPort">监听的端口</param> public AsyncTCPServer(IPAddress localIPAddress, int listenPort) { Address = localIPAddress; Port = listenPort; this.Encoding = Encoding.Default; _clients = new List<Object>(); _listener = new TcpListener(Address, Port); _listener.AllowNatTraversal(true); } #endregion #region Method /// <summary> /// 启动效劳器 /// </summary> public void Start() { if (!IsRunning) { IsRunning = true; _listener.Start(); _listener.BeginAcceptTcpClient( new AsyncCallback(HandleTcpClientAccepted), _listener); } } /// <summary> /// 启动效劳器 /// </summary> /// <param name="backlog"> /// 效劳器所许可的挂起衔接序列的最大长度 /// </param> public void Start(int backlog) { if (!IsRunning) { IsRunning = true; _listener.Start(backlog); _listener.BeginAcceptTcpClient( new AsyncCallback(HandleTcpClientAccepted), _listener); } } /// <summary> /// 住手效劳器 /// </summary> public void Stop() { if (IsRunning) { IsRunning = false; _listener.Stop(); lock (_clients) { //封闭一切客户端衔接 CloseAllClient(); } } } /// <summary> /// 处置惩罚客户端衔接的函数 /// </summary> /// <param name="ar"></param> private void HandleTcpClientAccepted(IAsyncResult ar) { if (IsRunning) { //TcpListener tcpListener = (TcpListener)ar.AsyncState; TcpClient client = _listener.EndAcceptTcpClient(ar); byte[] buffer = new byte[client.ReceiveBufferSize]; TCPClientState state = new TCPClientState(client, buffer); lock (_clients) { _clients.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) { TCPClientState state = (TCPClientState)ar.AsyncState; NetworkStream stream = state.NetworkStream; int recv = 0; try { recv = stream.EndRead(ar); } catch { recv = 0; } if (recv == 0) { // connection has been closed lock (_clients) { _clients.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); // 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) { RaisePrepareSend(state); Send(state.TcpClient, data); } /// <summary> /// 异步发送数据至指定的客户端 /// </summary> /// <param name="client">客户端</param> /// <param name="data">报文</param> public void Send(TcpClient client, byte[] data) { if (!IsRunning) throw new InvalidProgramException("This TCP Scoket server has not been started."); if (client == null) throw new ArgumentNullException("client"); if (data == null) throw new ArgumentNullException("data"); client.GetStream().BeginWrite(data, 0, data.Length, SendDataEnd, client); } /// <summary> /// 发送数据完成处置惩罚函数 /// </summary> /// <param name="ar">目的客户端Socket</param> private void SendDataEnd(IAsyncResult ar) { ((TcpClient)ar.AsyncState).GetStream().EndWrite(ar); RaiseCompletedSend(null); } #endregion #region 事宜 /// <summary> /// 与客户端的衔接已竖立事宜 /// </summary> public event EventHandler<AsyncEventArgs> ClientConnected; /// <summary> /// 与客户端的衔接已断开事宜 /// </summary> public event EventHandler<AsyncEventArgs> ClientDisconnected; /// <summary> /// 触发客户端衔接事宜 /// </summary> /// <param name="state"></param> private void RaiseClientConnected(TCPClientState state) { if (ClientConnected != null) { ClientConnected(this, new AsyncEventArgs(state)); } } /// <summary> /// 触发客户端衔接断开事宜 /// </summary> /// <param name="client"></param> private void RaiseClientDisconnected(TCPClientState state) { if (ClientDisconnected != null) { ClientDisconnected(this, new AsyncEventArgs("衔接断开")); } } /// <summary> /// 吸收到数据事宜 /// </summary> public event EventHandler<AsyncEventArgs> DataReceived; private void RaiseDataReceived(TCPClientState state) { if (DataReceived != null) { DataReceived(this, new AsyncEventArgs(state)); } } /// <summary> /// 发送数据前的事宜 /// </summary> public event EventHandler<AsyncEventArgs> PrepareSend; /// <summary> /// 触发发送数据前的事宜 /// </summary> /// <param name="state"></param> private void RaisePrepareSend(TCPClientState state) { if (PrepareSend != null) { PrepareSend(this, new AsyncEventArgs(state)); } } /// <summary> /// 数据发送终了事宜 /// </summary> public event EventHandler<AsyncEventArgs> CompletedSend; /// <summary> /// 触发数据发送终了的事宜 /// </summary> /// <param name="state"></param> private void RaiseCompletedSend(TCPClientState state) { if (CompletedSend != null) { CompletedSend(this, new AsyncEventArgs(state)); } } /// <summary> /// 收集毛病事宜 /// </summary> public event EventHandler<AsyncEventArgs> NetError; /// <summary> /// 触发收集毛病事宜 /// </summary> /// <param name="state"></param> private void RaiseNetError(TCPClientState state) { if (NetError != null) { NetError(this, new AsyncEventArgs(state)); } } /// <summary> /// 非常事宜 /// </summary> public event EventHandler<AsyncEventArgs> OtherException; /// <summary> /// 触发非常事宜 /// </summary> /// <param name="state"></param> private void RaiseOtherException(TCPClientState state, string descrip) { if (OtherException != null) { OtherException(this, new AsyncEventArgs(descrip, state)); } } private void RaiseOtherException(TCPClientState state) { RaiseOtherException(state, ""); } #endregion #region Close /// <summary> /// 封闭一个与客户端之间的会话 /// </summary> /// <param name="state">须要封闭的客户端会话对象</param> public void Close(TCPClientState state) { if (state != null) { state.Close(); _clients.Remove(state); _clientCount--; //TODO 触发封闭事宜 } } /// <summary> /// 封闭一切的客户端会话,与一切的客户端衔接会断开 /// </summary> public void CloseAllClient() { foreach (TCPClientState client in _clients) { Close(client); } _clientCount = 0; _clients.Clear(); } #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) { //TODO RaiseOtherException(null); } } disposed = true; } } #endregion } }
客户端处置惩罚封装类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; namespace NetFrame.Net.TCP.Listener.Asynchronous { public class TCPClientState { /// <summary> /// 与客户端相干的TcpClient /// </summary> public TcpClient TcpClient { get; private set; } /// <summary> /// 猎取缓冲区 /// </summary> public byte[] Buffer { get; private set; } /// <summary> /// 猎取收集流 /// </summary> public NetworkStream NetworkStream { get { return TcpClient.GetStream(); } } public TCPClientState(TcpClient tcpClient, byte[] buffer) { if (tcpClient == null) throw new ArgumentNullException("tcpClient"); if (buffer == null) throw new ArgumentNullException("buffer"); this.TcpClient = tcpClient; this.Buffer = buffer; } /// <summary> /// 封闭 /// </summary> public void Close() { //封闭数据的吸收和发送 TcpClient.Close(); Buffer = null; } } }
效劳器事宜参数类
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace NetFrame.Net.TCP.Listener.Asynchronous { /// <summary> /// 异步TcpListener TCP效劳器事宜参数类 /// </summary> public class AsyncEventArgs:EventArgs { /// <summary> /// 提醒信息 /// </summary> public string _msg; /// <summary> /// 客户端状况封装类 /// </summary> public TCPClientState _state; /// <summary> /// 是不是已处置惩罚过了 /// </summary> public bool IsHandled { get; set; } public AsyncEventArgs(string msg) { this._msg = msg; IsHandled = false; } public AsyncEventArgs(TCPClientState state) { this._state = state; IsHandled = false; } public AsyncEventArgs(string msg, TCPClientState state) { this._msg = msg; this._state = state; IsHandled = false; } } }
以上就是C#收集编程系列文章(三)之TcpListener完成异步TCP效劳器的内容,更多相干内容请关注ki4网(www.ki4.cn)!