首页/新闻资讯/正文详情

C#高性能TCP服务的多种实现方式

发布时间:2026/9/25 6:23:26 来源:云帆数科 栏目:资讯中心
C#高性能TCP服务的多种实现方式
C#高性能TCP服务的多种实现方式在高并发网络编程中TCP服务的性能优化至关重要。C# 提供了多种实现高性能TCP服务的途径从传统的Socket编程到现代的System.IO.Pipelines和SocketAsyncEventArgs每种方式都有其适用场景。本文将通过实战代码演示深入探讨几种主流实现方式。## 1. 基础Socket异步编程.NET 从早期开始就支持基于Begin/End模式的异步Socket操作。这种方式基于I/O完成端口IOCP但代码复杂度较高。csharpusing System;using System.Net;using System.Net.Sockets;using System.Text;public class BasicAsyncTcpServer{ private Socket _listenSocket; private const int BufferSize 1024; public void Start(int port) { _listenSocket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _listenSocket.Bind(new IPEndPoint(IPAddress.Any, port)); _listenSocket.Listen(100); // 最大挂起连接数 Console.WriteLine($TCP服务启动监听端口{port}); StartAccept(); } private void StartAccept() { // 异步接受客户端连接 _listenSocket.BeginAccept(new AsyncCallback(AcceptCallback), null); } private void AcceptCallback(IAsyncResult ar) { // 获取客户端Socket Socket clientSocket _listenSocket.EndAccept(ar); Console.WriteLine($客户端连接{clientSocket.RemoteEndPoint}); // 创建缓冲区接收数据 byte[] buffer new byte[BufferSize]; StateObject state new StateObject { WorkSocket clientSocket, Buffer buffer }; // 异步接收数据 clientSocket.BeginReceive(buffer, 0, BufferSize, 0, new AsyncCallback(ReceiveCallback), state); // 继续接受下一个客户端连接 StartAccept(); } private void ReceiveCallback(IAsyncResult ar) { StateObject state (StateObject)ar.AsyncState; Socket clientSocket state.WorkSocket; try { int bytesRead clientSocket.EndReceive(ar); if (bytesRead 0) { // 处理接收到的数据这里简单回显 string receivedData Encoding.ASCII.GetString(state.Buffer, 0, bytesRead); Console.WriteLine($收到数据{receivedData}); // 回显数据给客户端 byte[] sendData Encoding.ASCII.GetBytes($服务器回复{receivedData}); clientSocket.BeginSend(sendData, 0, sendData.Length, 0, new AsyncCallback(SendCallback), clientSocket); // 继续接收更多数据 Array.Clear(state.Buffer, 0, state.Buffer.Length); clientSocket.BeginReceive(state.Buffer, 0, BufferSize, 0, new AsyncCallback(ReceiveCallback), state); } else { // 连接关闭 clientSocket.Close(); Console.WriteLine(客户端断开连接); } } catch (Exception ex) { Console.WriteLine($接收错误{ex.Message}); clientSocket.Close(); } } private void SendCallback(IAsyncResult ar) { Socket clientSocket (Socket)ar.AsyncState; clientSocket.EndSend(ar); } private class StateObject { public Socket WorkSocket { get; set; } public byte[] Buffer { get; set; } }}优缺点分析- 优点底层API完全可控支持高并发- 缺点代码繁琐回调嵌套复杂容易出错## 2. SocketAsyncEventArgs 高性能模型SocketAsyncEventArgs是.NET 3.5引入的专门用于高性能Socket编程的类它通过对象池减少内存分配是构建高吞吐量服务器的理想选择。csharpusing System;using System.Collections.Generic;using System.Net;using System.Net.Sockets;using System.Threading;public class HighPerformanceTcpServer{ private Socket _listenSocket; private Semaphore _maxConnectionsSemaphore; private readonly int _bufferSize 1024; private readonly int _maxConnections 1000; public void Start(int port) { _listenSocket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _listenSocket.Bind(new IPEndPoint(IPAddress.Any, port)); _listenSocket.Listen(_maxConnections); // 使用信号量控制并发连接数 _maxConnectionsSemaphore new Semaphore(_maxConnections, _maxConnections); Console.WriteLine($高性能TCP服务启动监听端口{port}); // 创建并绑定一个监听用的SocketAsyncEventArgs SocketAsyncEventArgs acceptEventArgs new SocketAsyncEventArgs(); acceptEventArgs.Completed OnAcceptCompleted; // 开始异步接受连接 StartAccept(acceptEventArgs); } private void StartAccept(SocketAsyncEventArgs acceptEventArgs) { // 清理上一次的AcceptSocket如果有 acceptEventArgs.AcceptSocket null; // 等待信号量控制并发数 _maxConnectionsSemaphore.WaitOne(); // 异步接受连接 if (!_listenSocket.AcceptAsync(acceptEventArgs)) { // 同步完成 ProcessAccept(acceptEventArgs); } } private void OnAcceptCompleted(object sender, SocketAsyncEventArgs e) { ProcessAccept(e); } private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs) { Socket clientSocket acceptEventArgs.AcceptSocket; Console.WriteLine($客户端连接{clientSocket.RemoteEndPoint}); // 为当前连接创建读写使用的SocketAsyncEventArgs SocketAsyncEventArgs readEventArgs new SocketAsyncEventArgs(); readEventArgs.SetBuffer(new byte[_bufferSize], 0, _bufferSize); readEventArgs.UserToken clientSocket; readEventArgs.Completed OnIOCompleted; // 开始异步接收数据 if (!clientSocket.ReceiveAsync(readEventArgs)) { // 同步完成 ProcessReceive(readEventArgs); } // 继续接受下一个连接 StartAccept(acceptEventArgs); } private void OnIOCompleted(object sender, SocketAsyncEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Receive: ProcessReceive(e); break; case SocketAsyncOperation.Send: ProcessSend(e); break; } } private void ProcessReceive(SocketAsyncEventArgs e) { Socket clientSocket (Socket)e.UserToken; if (e.BytesTransferred 0 e.SocketError SocketError.Success) { // 处理接收到的数据这里简单回显 string receivedData System.Text.Encoding.ASCII.GetString(e.Buffer, 0, e.BytesTransferred); Console.WriteLine($收到数据{receivedData}); // 准备回显数据 byte[] sendData System.Text.Encoding.ASCII.GetBytes($服务器回复{receivedData}); e.SetBuffer(sendData, 0, sendData.Length); // 异步发送 if (!clientSocket.SendAsync(e)) { ProcessSend(e); } } else { // 连接关闭或出错 CloseClientSocket(e); } } private void ProcessSend(SocketAsyncEventArgs e) { Socket clientSocket (Socket)e.UserToken; if (e.SocketError SocketError.Success) { // 发送完成后继续接收新的数据 e.SetBuffer(new byte[_bufferSize], 0, _bufferSize); if (!clientSocket.ReceiveAsync(e)) { ProcessReceive(e); } } else { CloseClientSocket(e); } } private void CloseClientSocket(SocketAsyncEventArgs e) { Socket clientSocket (Socket)e.UserToken; try { clientSocket.Shutdown(SocketShutdown.Both); } catch { } clientSocket.Close(); // 释放信号量 _maxConnectionsSemaphore.Release(); Console.WriteLine(客户端断开连接); }}性能优势- 通过SocketAsyncEventArgs对象池减少GC压力- 使用信号量控制并发连接数避免资源耗尽- 所有IO操作完全异步不阻塞任何线程## 3. 基于 async/await 的现代实现.NET 4.5 引入了Task和async/await使异步编程变得简洁。Socket也提供了Task版本的扩展方法。csharpusing System;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading.Tasks;public class AsyncAwaitTcpServer{ private Socket _listenSocket; private const int BufferSize 1024; public async Task StartAsync(int port) { _listenSocket new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); _listenSocket.Bind(new IPEndPoint(IPAddress.Any, port)); _listenSocket.Listen(100); Console.WriteLine($async/await TCP服务启动监听端口{port}); while (true) { // 使用Task版本的AcceptAsync Socket clientSocket await _listenSocket.AcceptAsync(); Console.WriteLine($客户端连接{clientSocket.RemoteEndPoint}); // 不等待异步处理客户端 _ HandleClientAsync(clientSocket); } } private async Task HandleClientAsync(Socket clientSocket) { byte[] buffer new byte[BufferSize]; try { while (true) { // 异步接收数据 int bytesRead await clientSocket.ReceiveAsync(new ArraySegmentbyte(buffer), SocketFlags.None); if (bytesRead 0) break; string receivedData Encoding.ASCII.GetString(buffer, 0, bytesRead); Console.WriteLine($收到数据{receivedData}); // 异步回显 byte[] sendData Encoding.ASCII.GetBytes($服务器回复{receivedData}); await clientSocket.SendAsync(new ArraySegmentbyte(sendData), SocketFlags.None); } } catch (Exception ex) { Console.WriteLine($客户端处理错误{ex.Message}); } finally { clientSocket.Close(); Console.WriteLine(客户端断开连接); } }}核心优势- 代码简洁易读如同同步编程- 自动处理线程调度- 适合中小规模并发## 4. 使用 System.IO.Pipelines 的高效处理.NET Core 2.1 引入的System.IO.Pipelines专为高性能I/O设计特别适合处理大量数据流。csharpusing System;using System.Buffers;using System.IO.Pipelines;using System.Net;using System.Net.Sockets;using System.Text;using System.Threading.Tasks;public class PipelineTcpServer{ public async Task StartAsync(int port) { var listener new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); listener.Bind(new IPEndPoint(IPAddress.Any, port)); listener.Listen(100); Console.WriteLine($Pipeline TCP服务启动监听端口{port}); while (true) { var clientSocket await listener.AcceptAsync(); _ ProcessClientAsync(clientSocket); } } private async Task ProcessClientAsync(Socket socket) { var pipe new Pipe(); var writerTask FillPipeAsync(socket, pipe.Writer); var readerTask ReadPipeAsync(socket, pipe.Reader); await Task.WhenAll(writerTask, readerTask); } private async Task FillPipeAsync(Socket socket, PipeWriter writer) { const int minimumBufferSize 512; try { while (true) { // 从PipeWriter获取内存 Memorybyte memory writer.GetMemory(minimumBufferSize); // 从Socket读取数据 int bytesRead await socket.ReceiveAsync(memory, SocketFlags.None); if (bytesRead 0) break; // 通知PipeWriter已经写了多少数据 writer.Advance(bytesRead); // 将数据刷新到PipeReader FlushResult result await writer.FlushAsync(); if (result.IsCompleted) break; } } catch (Exception ex) { Console.WriteLine($写入管道错误{ex.Message}); } finally { await writer.CompleteAsync(); } } private async Task ReadPipeAsync(Socket socket, PipeReader reader) { try { while (true) { ReadResult result await reader.ReadAsync(); ReadOnlySequencebyte buffer result.Buffer; // 处理数据这里简单解析并回显 foreach (var segment in buffer) { string receivedData Encoding.ASCII.GetString(segment.Span); if (!string.IsNullOrEmpty(receivedData)) { Console.WriteLine($收到数据{receivedData}); // 回显数据 byte[] sendData Encoding.ASCII.GetBytes($服务器回复{receivedData}); await socket.SendAsync(new ArraySegmentbyte(sendData), SocketFlags.None); } } // 通知PipeReader我们已经处理完数据 reader.AdvanceTo(buffer.End); if (result.IsCompleted) break; } } catch (Exception ex) { Console.WriteLine($读取管道错误{ex.Message}); } finally { await reader.CompleteAsync(); } }}Pipeline 优势- 自动内存管理减少拷贝- 高效处理流式数据- 内置背压机制## 5. 性能对比与选型建议| 实现方式 | 并发能力 | 代码复杂度 | 内存效率 | 适用场景 ||---------|---------|-----------|---------|---------|| Begin/End | 高 | 高 | 中 | 遗留系统维护 || SocketAsyncEventArgs | 极高 | 中 | 高 | 游戏服务器、金融交易 || async/await | 中 | 低 | 中 | Web API、聊天应用 || Pipelines | 高 | 中 | 极高 | 文件传输、日志处理 |## 总结C#提供了多种高性能TCP服务实现方案从底层的SocketAsyncEventArgs到现代的async/await和System.IO.Pipelines。选择哪种方式取决于具体需求- 如果追求极致性能如每秒处理数万连接SocketAsyncEventArgs配合对象池是最佳选择- 如果注重开发效率和可维护性async/await模式提供了最简洁的编程体验- 如果处理大量流式数据如文件上传、视频流System.IO.Pipelines的内存管理优势显著在实际项目中建议从async/await入手在遇到性能瓶颈时再逐步优化到更底层的方案。记住最好的优化是避免过早优化——先用最简单的方案实现功能然后通过性能分析工具定位瓶颈再有针对性地进行优化。

相关推荐

C++实现Everest期权量化测试:蒙特卡洛模拟与并行计算实战
C++实现Everest期权量化测试:蒙特卡洛模拟与并行计算实战

1. 项目概述:量化交易中的“埃弗勒斯峰”挑战 在量化交易的策略开发领域,我们常常会遇到一些结构复杂、风险收益特征独特的金融衍生品。今天要聊的这个项目,就是围绕一个听起来就很有挑战性的概念——“Everest Option”(埃弗勒斯… · 2026/9/25 6:23:22

专科生论文写作必备:10款AIGC工具全攻略与降重技巧
专科生论文写作必备:10款AIGC工具全攻略与降重技巧

1. 专科生必备AIGC工具指南:从入门到过审全攻略作为一名在学术写作领域摸爬滚打多年的老手,我深知专科生在论文写作和降重过程中面临的困境。最近两年,AIGC工具的爆发式发展为学术写作带来了革命性变化。但面对市面上琳琅满目的工具&#xff… · 2026/8/1 14:01:54

TMS320C6000 DSP利用McBSP实现UART通信的两种方案详解
TMS320C6000 DSP利用McBSP实现UART通信的两种方案详解

1. 项目概述在嵌入式系统开发中,串口通信(UART)几乎是调试、数据交换和系统监控的“标配”。然而,当你手头的TMS320C6000系列DSP没有硬件UART外设时,是不是感觉有点束手无策?别急,它的多通道缓冲… · 2026/8/8 23:08:31

CSM331A四种CAN扩展模式选型与工程落地指南
CSM331A四种CAN扩展模式选型与工程落地指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:23:17

西工大NOJ前100题刷题指南:从C语言基础到指针递归的进阶修炼
西工大NOJ前100题刷题指南:从C语言基础到指针递归的进阶修炼

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 6:23:17

Atlas 300V加速卡部署YOLO实战:从模型转换到推理调优
Atlas 300V加速卡部署YOLO实战:从模型转换到推理调优

最近在折腾视频分析项目的推理硬件,从GPU一路试到华为的Atlas系列,手头这块Atlas 300V 24G算是用了最久的。如果你正好也在纠结“Atlas 300V 24G到底是不是运算加速卡”,或者想在它上面把YOLO跑起来,这篇应该能帮你少走不少弯路。… · 2026/9/25 6:23:11

C++语言基础与关键字解析:从数据类型到工程实践
C++语言基础与关键字解析:从数据类型到工程实践

1. C语言基础与关键字解析C作为一门经典的编程语言,其关键字系统构成了语法体系的核心骨架。对于初学者而言,全面掌握这些关键字不仅能够避免语法错误,更能深入理解语言设计哲学。让我们从实际开发角度重新梳理这些关键元素。1.1 数据类型关键… · 2026/9/25 6:23:05

Git密码认证被禁用?SSH密钥与PAT安全配置指南
Git密码认证被禁用?SSH密钥与PAT安全配置指南

1. 这个报错不是Git的问题,而是你正在被Git服务端“礼貌拒收”提示:remote: Invalid username or token. Password authentication is not supported for Git operations—— 这行红字不是Git客户端出错了,它是一份来自GitHub、GitLab、Gitee… · 2026/9/25 6:23:05

Tomcat线程模型与OOM问题深度解析
Tomcat线程模型与OOM问题深度解析

1. 问题背景与现象分析最近在排查一个线上服务异常时,遇到了一个典型的OOM(OutOfMemoryError)问题。这个案例非常有意思,因为它不仅涉及到内存溢出本身,还引发了Tomcat线程模型的异常表现,最终导致服务不可… · 2026/9/25 6:22:58

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码