TcpListener 類別提供一些簡單方法,用於在阻止同步模式下偵聽和接受傳入連線請求。 可使用 TcpClient 或 Socket 來連接 TcpListener。 可使用 IPEndPoint、本機 IP 位址及連接埠號碼或僅使用連接埠號,來建立 TcpListener。 可以將本機 IP 位址指定為 Any,將本機連接埠號碼指定為 0(如果希望基礎服務提供者為您指派這些值)。 如果您選擇這樣做,可在連接套接字後使用 LocalEndpoint 屬性來識別已指定的資訊。使用 Start 方法,可開始偵聽傳入的連線要求。
Start 將對傳入連線進行排隊,直到您呼叫 Stop 方法或它已完成 MaxConnections 排隊為止。 可使用 AcceptSocket 或 AcceptTcpClient 從傳入連線請求佇列提取連線。 這兩種方法將阻止。 如果要避免阻止,可先使用 Pending 方法來確定佇列中是否有可用的連線要求。
雖然TcpListener已經封裝的比較不錯了,我們於是就使用它在建構一個比較不錯的同步TCP伺服器,這裡依然和前兩章一樣,給出伺服器中的程式碼,程式碼中註解很詳細,我也會給出相關的封裝類別。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Net; using System.Threading; namespace NetFrame.Net.TCP.Listener.Synchronous { /// <summary> /// TcpListener实现同步TCP服务器 /// </summary> public class TCPServer { #region Fields /// <summary> /// 服务器程序允许的最大客户端连接数 /// </summary> private int _maxClient; /// <summary> /// 当前的连接的客户端数 /// </summary> private int _clientCount; /// <summary> /// 服务器使用的异步TcpListener /// </summary> private TcpListener _listener; /// <summary> /// 客户端会话列表 /// </summary> private List<TCPClientHandle> _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 TCPServer(int listenPort) : this(IPAddress.Any, listenPort, 1024) { } /// <summary> /// 同步TCP服务器 /// </summary> /// <param name="localEP">监听的终结点</param> public TCPServer(IPEndPoint localEP) : this(localEP.Address, localEP.Port, 1024) { } /// <summary> /// 同步TCP服务器 /// </summary> /// <param name="localIPAddress">监听的IP地址</param> /// <param name="listenPort">监听的端口</param> /// <param name="maxClient">最大客户端数量</param> public TCPServer(IPAddress localIPAddress, int listenPort, int maxClient) { this.Address = localIPAddress; this.Port = listenPort; this.Encoding = Encoding.Default; _maxClient = maxClient; _clients = new List<TCPClientHandle>(); _listener = new TcpListener(new IPEndPoint(this.Address, this.Port)); } #endregion #region Method /// <summary> /// 启动服务器 /// </summary> public void Start() { if (!IsRunning) { IsRunning = true; _listener.Start(); Thread thread = new Thread(Accept); thread.Start(); } } /// <summary> /// 开始进行监听 /// </summary> private void Accept() { TCPClientHandle handle; while (IsRunning) { TcpClient client = _listener.AcceptTcpClient(); if (_clientCount >= _maxClient) { //TODO 触发事件 } else { handle = new TCPClientHandle(client); _clientCount++; _clients.Add(handle); //TODO 创建一个处理客户端的线程并启动 //使用线程池来操作 new Thread(new ThreadStart(handle.RecevieData)).Start(); } } } /// <summary> /// 停止服务器 /// </summary> public void Stop() { if (IsRunning) { IsRunning = false; _listener.Stop(); //TODO 关闭对所有客户端的连接 } } /// <summary> /// 发送函数 /// </summary> public void Send(string msg, TcpClient client) { //TODO } #endregion #region 事件 /// <summary> /// 与客户端的连接已建立事件 /// </summary> public event EventHandler<TCPEventArgs> ClientConnected; /// <summary> /// 与客户端的连接已断开事件 /// </summary> public event EventHandler<TCPEventArgs> ClientDisconnected; /// <summary> /// 触发客户端连接事件 /// </summary> /// <param name="state"></param> private void RaiseClientConnected(TCPClientHandle handle) { if (ClientConnected != null) { ClientConnected(this, new TCPEventArgs(handle)); } } /// <summary> /// 触发客户端连接断开事件 /// </summary> /// <param name="client"></param> private void RaiseClientDisconnected(Socket client) { if (ClientDisconnected != null) { ClientDisconnected(this, new TCPEventArgs("连接断开")); } } /// <summary> /// 接收到数据事件 /// </summary> public event EventHandler<TCPEventArgs> DataReceived; private void RaiseDataReceived(TCPClientHandle handle) { if (DataReceived != null) { DataReceived(this, new TCPEventArgs(handle)); } } /// <summary> /// 数据发送事件 /// </summary> public event EventHandler<TCPEventArgs> CompletedSend; /// <summary> /// 触发数据发送事件 /// </summary> /// <param name="state"></param> private void RaiseCompletedSend(TCPClientHandle handle) { if (CompletedSend != null) { CompletedSend(this, new TCPEventArgs(handle)); } } /// <summary> /// 网络错误事件 /// </summary> public event EventHandler<TCPEventArgs> NetError; /// <summary> /// 触发网络错误事件 /// </summary> /// <param name="state"></param> private void RaiseNetError(TCPClientHandle handle) { if (NetError != null) { NetError(this, new TCPEventArgs(handle)); } } /// <summary> /// 异常事件 /// </summary> public event EventHandler<TCPEventArgs> OtherException; /// <summary> /// 触发异常事件 /// </summary> /// <param name="state"></param> private void RaiseOtherException(TCPClientHandle handle, string descrip) { if (OtherException != null) { OtherException(this, new TCPEventArgs(descrip, handle)); } } private void RaiseOtherException(TCPClientHandle handle) { RaiseOtherException(handle, ""); } #endregion #region Close /// <summary> /// 关闭一个与客户端之间的会话 /// </summary> /// <param name="handle">需要关闭的客户端会话对象</param> public void Close(TCPClientHandle handle) { if (handle != null) { _clients.Remove(handle); handle.Dispose(); _clientCount--; //TODO 触发关闭事件 } } /// <summary> /// 关闭所有的客户端会话,与所有的客户端连接会断开 /// </summary> public void CloseAllClient() { foreach (TCPClientHandle handle in _clients) { Close(handle); } _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 异常 } } disposed = true; } } #endregion } }
客戶端處理封裝類別
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.IO; namespace NetFrame.Net.TCP.Listener.Synchronous { /// <summary> /// TcpListener实现同步TCP服务器 的客户端连接处理类 /// </summary> public class TCPClientHandle { private TcpClient _tcpclient; private BinaryReader rs; private BinaryWriter ws; /// <summary> /// 标识是否与客户端相连接 /// </summary> private bool _is_connect; public bool IsConnect { get { return _is_connect; } set { _is_connect = value; } } /// <summary> /// 数据接受缓冲区 /// </summary> private byte[] _recvBuffer; public TCPClientHandle(TcpClient client) { _tcpclient = client; rs = new BinaryReader(client.GetStream()); ws = new BinaryWriter(client.GetStream()); // NetworkStream ns = tmpTcpClient.GetStream(); // if(ns.CanRead&&ns.CanWrite) _recvBuffer=new byte[client.ReceiveBufferSize]; } /// <summary> /// 接受数据 /// </summary> public void RecevieData() { int len = 0; while (_is_connect) { try { len = rs.Read(_recvBuffer, 0, _recvBuffer.Length); } catch (Exception) { break; } if (len == 0) { //the client has disconnected from server break; } //TODO 处理收到的数据 } } /// <summary> /// 向客户端发送数据 /// </summary> /// <param name="msg"></param> public void SendData(string msg) { byte[] data = Encoding.Default.GetBytes(msg); try { ws.Write(data, 0, data.Length); ws.Flush(); } catch (Exception) { //TODO 处理异常 } } #region 事件 //TODO 消息发送事件 //TODO 数据收到事件 //TODO 异常处理事件 #endregion #region 释放 /// <summary> /// Performs application-defined tasks associated with freeing, /// releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { _is_connect = false; if (_tcpclient != null) { _tcpclient.Close(); _tcpclient = null; } GC.SuppressFinalize(this); } #endregion } }
Tcp伺服器事件參數類別
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace NetFrame.Net.TCP.Listener.Synchronous { /// <summary> /// 同步TcpListener TCP服务器事件类 /// </summary> public class TCPEventArgs : EventArgs { /// <summary> /// 提示信息 /// </summary> public string _msg; /// <summary> /// 客户端状态封装类 /// </summary> public TCPClientHandle _handle; /// <summary> /// 是否已经处理过了 /// </summary> public bool IsHandled { get; set; } public TCPEventArgs(string msg) { this._msg = msg; IsHandled = false; } public TCPEventArgs(TCPClientHandle handle) { this._handle = handle; IsHandled = false; } public TCPEventArgs(string msg, TCPClientHandle handle) { this._msg = msg; this._handle = handle; IsHandled = false; } } }
以上就是C#網路程式設計系列文章(四)之TcpListener實作同步TCP伺服器的內容,更多相關內容請關注PHP中文網(www.php.cn)!