本文介绍
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服务器的内容,更多相关内容请关注PHP中文网(www.php.cn)!

C#在.NET中的编程过程包括以下步骤:1)编写C#代码,2)编译为中间语言(IL),3)由.NET运行时(CLR)执行。C#在.NET中的优势在于其现代化语法、强大的类型系统和与.NET框架的紧密集成,适用于从桌面应用到Web服务的各种开发场景。

C#是一种现代、面向对象的编程语言,由微软开发并作为.NET框架的一部分。1.C#支持面向对象编程(OOP),包括封装、继承和多态。2.C#中的异步编程通过async和await关键字实现,提高应用的响应性。3.使用LINQ可以简洁地处理数据集合。4.常见错误包括空引用异常和索引超出范围异常,调试技巧包括使用调试器和异常处理。5.性能优化包括使用StringBuilder和避免不必要的装箱和拆箱。

C#.NET应用的测试策略包括单元测试、集成测试和端到端测试。1.单元测试确保代码的最小单元独立工作,使用MSTest、NUnit或xUnit框架。2.集成测试验证多个单元组合的功能,常用模拟数据和外部服务。3.端到端测试模拟用户完整操作流程,通常使用Selenium进行自动化测试。

C#高级开发者面试需要掌握异步编程、LINQ、.NET框架内部工作原理等核心知识。1.异步编程通过async和await简化操作,提升应用响应性。2.LINQ以SQL风格操作数据,需注意性能。3..NET框架的CLR管理内存,垃圾回收需谨慎使用。

C#.NET面试问题和答案包括基础知识、核心概念和高级用法。1)基础知识:C#是微软开发的面向对象语言,主要用于.NET框架。2)核心概念:委托和事件允许动态绑定方法,LINQ提供强大查询功能。3)高级用法:异步编程提高响应性,表达式树用于动态代码构建。

C#.NET是构建微服务的热门选择,因为其生态系统强大且支持丰富。1)使用ASP.NETCore创建RESTfulAPI,处理订单创建和查询。2)利用gRPC实现微服务间的高效通信,定义和实现订单服务。3)通过Docker容器化微服务,简化部署和管理。

C#和.NET的安全最佳实践包括输入验证、输出编码、异常处理、以及身份验证和授权。1)使用正则表达式或内置方法验证输入,防止恶意数据进入系统。2)输出编码防止XSS攻击,使用HttpUtility.HtmlEncode方法。3)异常处理避免信息泄露,记录错误但不返回详细信息给用户。4)使用ASP.NETIdentity和Claims-based授权保护应用免受未授权访问。

C 语言中冒号 (':') 的含义:条件语句:分隔条件表达式和语句块循环语句:分隔初始化、条件和增量表达式宏定义:分隔宏名和宏值单行注释:表示从冒号到行尾的内容为注释数组维数:指定数组的维数


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

Dreamweaver Mac版
视觉化网页开发工具

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。