


C# network programming series of articles (3) TcpListener implements asynchronous TCP server
Introduction to this article
The TcpListener class provides some simple methods for listening and accepting incoming connection requests in blocking synchronization mode. TcpListener can be connected using TcpClient or Socket. A TcpListener can be created using an IPEndPoint, a local IP address and a port number, or just a port number. You can specify the local IP address as Any and the local port number as 0 if you want the underlying service provider to assign these values for you.
If you choose to do this, you can use the LocalEndpoint property to identify the specified information after connecting to the socket. Use the Start method to start listening for incoming connection requests. Start will queue incoming connections until you call the Stop method or it has completed queuing MaxConnections. You can use AcceptSocket or AcceptTcpClient to extract connections from the queue of incoming connection requests. Both methods will block. If you want to avoid blocking, first use the Pending method to determine whether there are available connection requests in the queue.
Although TcpListener has been encapsulated relatively well, we use it to construct a relatively good asynchronous TCP server. Here it is still the same as the first two As in the chapter, I will give the code in the server. The comments in the code are very detailed, and I will also give the relevant encapsulation classes.
TcpListener asynchronous TCP server
Server code
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 } }
Client processing encapsulation class
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; } } }
Server event parameter class
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; } } }
The above is the content of TcpListener to implement asynchronous TCP server in C# network programming series article (3). For more related content, please pay attention to the PHP Chinese website (www.php.cn)!

C#.NETissuitableforenterprise-levelapplicationswithintheMicrosoftecosystemduetoitsstrongtyping,richlibraries,androbustperformance.However,itmaynotbeidealforcross-platformdevelopmentorwhenrawspeediscritical,wherelanguageslikeRustorGomightbepreferable.

The programming process of C# in .NET includes the following steps: 1) writing C# code, 2) compiling into an intermediate language (IL), and 3) executing by the .NET runtime (CLR). The advantages of C# in .NET are its modern syntax, powerful type system and tight integration with the .NET framework, suitable for various development scenarios from desktop applications to web services.

C# is a modern, object-oriented programming language developed by Microsoft and as part of the .NET framework. 1.C# supports object-oriented programming (OOP), including encapsulation, inheritance and polymorphism. 2. Asynchronous programming in C# is implemented through async and await keywords to improve application responsiveness. 3. Use LINQ to process data collections concisely. 4. Common errors include null reference exceptions and index out-of-range exceptions. Debugging skills include using a debugger and exception handling. 5. Performance optimization includes using StringBuilder and avoiding unnecessary packing and unboxing.

Testing strategies for C#.NET applications include unit testing, integration testing, and end-to-end testing. 1. Unit testing ensures that the minimum unit of the code works independently, using the MSTest, NUnit or xUnit framework. 2. Integrated tests verify the functions of multiple units combined, commonly used simulated data and external services. 3. End-to-end testing simulates the user's complete operation process, and Selenium is usually used for automated testing.

Interview with C# senior developer requires mastering core knowledge such as asynchronous programming, LINQ, and internal working principles of .NET frameworks. 1. Asynchronous programming simplifies operations through async and await to improve application responsiveness. 2.LINQ operates data in SQL style and pay attention to performance. 3. The CLR of the NET framework manages memory, and garbage collection needs to be used with caution.

C#.NET interview questions and answers include basic knowledge, core concepts, and advanced usage. 1) Basic knowledge: C# is an object-oriented language developed by Microsoft and is mainly used in the .NET framework. 2) Core concepts: Delegation and events allow dynamic binding methods, and LINQ provides powerful query functions. 3) Advanced usage: Asynchronous programming improves responsiveness, and expression trees are used for dynamic code construction.

C#.NET is a popular choice for building microservices because of its strong ecosystem and rich support. 1) Create RESTfulAPI using ASP.NETCore to process order creation and query. 2) Use gRPC to achieve efficient communication between microservices, define and implement order services. 3) Simplify deployment and management through Docker containerized microservices.

Security best practices for C# and .NET include input verification, output encoding, exception handling, as well as authentication and authorization. 1) Use regular expressions or built-in methods to verify input to prevent malicious data from entering the system. 2) Output encoding to prevent XSS attacks, use the HttpUtility.HtmlEncode method. 3) Exception handling avoids information leakage, records errors but does not return detailed information to the user. 4) Use ASP.NETIdentity and Claims-based authorization to protect applications from unauthorized access.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

MantisBT
Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Safe Exam Browser
Safe Exam Browser is a secure browser environment for taking online exams securely. This software turns any computer into a secure workstation. It controls access to any utility and prevents students from using unauthorized resources.

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Dreamweaver Mac version
Visual web development tools