C# IOCP SocketAsyncEventArgs 使用流程

C#使用SocketAsyncEventArgs实现Socket客户端通信 用System.Net.Sockets.Socket类实现tcp通信并不简单,需要大量代码去实现,但其接近底层而可以发挥更高的效率,本文的目标是实现高性能的套接字客户端,否则没有使用Socket的必要,而应该使用更为简单易用的System.Net.Sockets.TcpClient 首先是参考资料,第一当然是微软的文档(https://docs.microsoft.com/zh-cn/dotnet/api/system.net.sockets.socket?view=netcore-3.1),其次是其他人 阅读详情

IOCP 的SocketAsyncEventArgs实现流程

在这里插入图片描述

上述为IOCP执行过程,具体代码参见SocketAsyncEventArgs 类 (System.Net.Sockets) | Microsoft Learn

关于上图以及IOCP实现过程中的注解:

  1. 在请求较为频繁或连接时间相对较短时,异步事件需要频繁实例化,会降低并发性能,建议使用异步事件的对象池(SocketAsyncEventArgsPool)和缓存池来分配事件和缓冲区。

  2. 缓冲区必须进行显式设置,类型为byte[]或IList<ArraySegment<byte>>,必须有且只有一个,若二者都进行分配,将会报错。官方错误注解如下:

ArgumentException

参数无效。 e 参数的 Buffer 或 BufferList 属性必须引用有效的缓冲区。 可以设置这两个属性中的某一个,但不能同时设置这两个属性。

  1. 在Windows系统下,该异步方法采用IOCP来实现,在Linux方法下通过epoll来实现,C#原生Socket仅有Select能够支持简单的“并发”,如果想在Linux平台实现高效率,可以采用此方法以达到epoll的效率。

  2. 从上图不难看出:如果极端情况下,Accept后的Socket会一直或较长一段时间内处于同步状态,此时将会占用主线程来执行相关数据处理工作,会影响后续Socket的Accept。因此如果采用上述流程,应当尽可能避免将待收发数据的预处理操作放到完成事件绑定的方法内。通常的解决方法是将接收到的数据传入一个用线程池执行的方法内或创建一个Channel,将数据发往对应数据处理线程。但也可能会有人想要从Accept同步的角度去解决问题,但要注意异步方法的使用位置,一旦使用不当很容易引发错误。看如下官方代码:

public void StartAccept(SocketAsyncEventArgs acceptEventArg)
{
    // loop while the method completes synchronously
    bool willRaiseEvent = false;
    while (!willRaiseEvent)
    {
        m_maxNumberAcceptedClients.WaitOne();
        // socket must be cleared since the context object is being reused
        acceptEventArg.AcceptSocket = null;       //标记代码行 2     
        willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg);
        if (!willRaiseEvent)
        {
            ProcessAccept(acceptEventArg);        //标记代码行 1
        }
     }
}

private void ProcessAccept(SocketAsyncEventArgs e)
{
    Interlocked.Increment(ref m_numConnectedSockets);
    Console.WriteLine("Client connection accepted. There are {0} clients connected to the server",m_numConnectedSockets);
    // Get the socket for the accepted client connection and put it into the
    //ReadEventArg object user token
    SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop();
    readEventArgs.UserToken = e.AcceptSocket;    //标记代码行 3
    // As soon as the client is connected, post a receive to the connection
    bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs);
    if (!willRaiseEvent)
    {
        ProcessReceive(readEventArgs);        //标记代码行 4
    }
}

        如果要从Accept方面解决同步问题,需要在 “标记代码行 1” 或 “标记代码行 4” 处采用异步(await、ThreadPool、Thread、Task),在 “1” 处采用异步,是将接收到的Socket异步事件初始分配及后续步骤作为异步操作,但如果观察一下 “2” 和 “3” 不难发现,如果采用异步,当前Socket异步执行ProcessAccept的过程和主线程执行StartAccept的过程是并行的,无法确定 “2” 和 “3” 的先后顺序,这样很可能会造成先将acceptEventArg.AcceptSocket指定为null,后将e.AcceptSocket赋给readEventArgs.UserToken(此处e和acceptEventArg指向同一对象)。因此在ProcessAccept处使用异步会产生空引用错误;如果在 “4” 处采用异步,则初始化后将同步接收代码交由异步处理,后续操作则不会引发错误。

  1. 上图中的执行流程很好地演示了SocketAsyncEventArgs类的异步收发数据以及初始化配置过程,但并不应当直接用于生产。因为该演示流程存在一个重大问题:异步接收和异步发送之间是同步关系。换句话说就是虽然是异步收发,但收和发两个动作是相互调用对方的异步函数,二者之间的顺序实则是同步的环状结构。相对来说,异步发送并不会占用太多时间(相对),因此接收函数能够很快地被调用并进行监听,但问题在于传统的Socket是收发并行的,服务端与客户端可以双向通信,并不依赖于某一方的主动操作,而上述流程如果出现发送方迟迟不发送的情况,即ReceiveAsync的完成事件迟迟不触发,则会一直“异步阻塞”下去,导致永远不会调用SendAsync。因此通常情况下需要分别调用发送和接收的异步函数并对自身异步递归调用。但需要注意的是,二者同时触发时,不可共用同一个异步事件,需要分别进行注册,官方提供错误注解如下:

InvalidOperationException

已经在使用 e 参数中指定的 SocketAsyncEventArgs 对象执行套接字操作。

C#高性能Socket服务器SocketAsyncEventArgs的实现(IOCP) 原创性申明 本文作者:小竹zz  博客地址:http://blog.youkuaiyun.com/zhujunxxxxx 转载请注明出处 引言 我一直在探寻一个高性能的Socket客户端代码。以前,我使用Socket类写了一些基于传统异步编程模型的代码(BeginSend、BeginReceive,等等)也看过很多博客的知识,在linux中有poll和epoll来实现,在windows下面 微软MSD 阅读详情

相关推荐

自写C#高性能Socket服务器SocketAsyncEventArgs

版权声明: https://blog.youkuaiyun.com/zhujunxxxxx/article/details/43573879 原创性申明 本文作者:落落 博客地址:https://download.youkuaiyun.com/download/sinat_37015261/11199702转载请注明出处 引言 我一直在探寻一个高性能的Socket客户端代码。以前,我使用Socket类写了一些基于传统异...

不二、落落的博客 769

c# SocketAsyncEventArgs例子包含服务端和客户端

c# SocketAsyncEventArgs高性能socket例子包含服务端和客户端

SocketAsyncEventArgs 高性能 Socket 通信实战:从端口压测翻车到 IOCP 优化

在高并发网络编程中,IOCP(IO 完成端口)是提升吞吐量的核心机制,而 SocketAsyncEventArgs 则是 .NET 中实现 IOCP 高性能通信的关键类。其原理在于通过对象池复用和事件回调,避免每次异步 IO 都分配新对象,从而大幅降低 GC 压力与线程阻塞。技术价值体现在内存占用恒定、延迟稳定,尤其适合 C# 上位机、GB28181 及物联网采集服务端等场景。当连接数达到数十上百或对延迟敏感时,合理使用 SocketAsyncEventArgs 能有效解决传统异步模型的内存暴涨与 GC 频

weixin_31031711的博客 208

c#写的iocp服务端和客户端代码

用c#语言写的iocp网络服务,和客户端,有注释,程序可直接运行

C#高性能SOCKET并发:完成端口(IOCP)从原理到实践

高并发连接是服务端开发永恒的挑战。传统阻塞Socket每连接一线程,线程上下文切换和内存开销让系统在数千连接时即陷入瓶颈。Windows完成端口(IOCP)作为内核级异步I/O模型,通过完成包统一投递和少量工作线程消费,极大降低了线程调度成本,是支撑十万级长连接的核心技术。IOCP的C#实现通常借助SocketAsyncEventArgs,它对应底层OVERLAPPED结构,可池化复用,避免GC压力,适合构建高吞吐网关。在即时通讯、游戏网关、IoT接入等场景中,基于IOCP的并发服务能有效降低CPU占用和内

weixin_32308101的博客 217

C# IOCP完成端口实现高性能Socket并发服务器:原理、架构与压测实战

在物联网、游戏服务器与消息推送等高并发场景中,传统Socket编程常因线程开销和上下文切换而性能骤降。完成端口(IOCP)作为Windows内核级异步I/O机制,通过将Socket句柄绑定至完成端口对象,由少量工作线程处理I/O完成通知,从根本上解决了大规模连接下的资源瓶颈。C#开发者借助SocketAsyncEventArgs和对象池复用技术,能够进一步降低GC压力,实现可控的收发状态机与可靠的数据边界处理。这类架构在物联网网关、IM服务等场景中具备极高的工程价值。本文以一套完整的C# IOCP服务器客户

weixin_33585822的博客 245

C# 使用.NET的SocketAsyncEventArgs实现高效能多并发TCPSocket通信

AsyncUserToken类。SocketManager类。BufferManager类。

a876106354的博客 3629

C# IOCP高并发Socket实战:完成端口与SocketAsyncEventArgs解析

完成端口(IOCP)是Windows下处理高并发网络I/O的核心机制,它通过让操作系统统一管理海量套接字的I/O完成通知,从根本上避免了“一个连接一个线程”带来的线程爆炸与上下文切换开销。SocketAsyncEventArgs是.NET为高性能服务器设计的异步模型,通过对象复用显著降低内存分配与GC压力。理解IOCP的线程模型与SocketAsyncEventArgs的工作方式,有助于构建即时通讯、游戏网关、物联网接入等高并发后端服务。本文围绕完成端口和SocketAsyncEventArgs,拆解从Ac

weixin_33552698的博客 276

如何使用 SocketAsyncEventArgs 类

APM 自第一个版本起就在 .NET Framework 中实现,并使用 C# 3.0 中的 lambda 表达式等新技术进行改进。特别是对于套接字编程,APM 的新模型提供了更简单的编码,更不用说性能优势了。然后,我发现了基于事件的异步操作的新模型(请参阅MSDN 杂志 2007 年 9 月号中的“尽管MSDN说该类是专门为网络服务器应用程序设计的,但在客户端代码中使用该APM并没有限制。,本文中的代码是使用 Microsoft Visual Studio .NET 2008 编写的。

君子居易 933

构建基于 IOCP 的高效 C# Socket 服务器

在计算机网络中,Socket是用于实现网络通信的端点,它提供了不同主机上运行的应用程序进行数据交换的接口。C#中的Socket编程允许开发者通过编程方式控制网络通信,从简单的HTTP请求到复杂的自定义协议通信。Socket编程模型主要涉及以下几个方面:Socket类型:常用的有流式Socket()和数据报Socket(地址族:定义地址格式和协议族,如IPv4()和IPv6(协议:用于Socket通信的具体协议,例如TCP()和UDP(

weixin_42355400的博客 1029

SocketAsyncEventArgs与IOCP高并发异步Socket避坑

异步I/O是构建高并发网络服务的基础。在Windows平台上,IOCP(I/O完成端口)通过内核队列管理大量并发连接,避免“一连接一线程”的资源开销。C#的SocketAsyncEventArgs正是为配合IOCP而生的异步Socket组件,借助事件驱动与对象复用机制,减少对象分配和线程上下文切换,从而提升系统吞吐量。本文结合可运行的IOCPServer和Client样例,深入讲解SocketAsyncEventArgs的用法、服务端与客户端的收发模型,以及缓冲区管理、半包/粘包处理等工程实践,并总结对象池

weixin_34082789的博客 295

C#完成端口IOCP:(01)SocketAsyncEventArgs封装

重写SocketAsyncEventArgs,实现ReadAsync和WriteAsync以及SocketAsyncEventArgs的复用。重写的SocketAsyncEventArgs没有太多逻辑,就是把SocketAsyncEventArgs的事件改成了回调,内部还是调用Socket的对应方法。

艾恩 1475

C#高并发长连接实战:SocketAsyncEventArgs与IOCP性能优化

在C#网络编程中,高并发长连接场景常面临线程池饥饿与GC压力。SocketAsyncEventArgs基于IOCP(IO完成端口)实现异步非阻塞通信,通过缓冲区复用与事件回调机制,显著降低上下文切换与内存分配。其技术价值在于支撑数千连接下CPU与内存稳定,适用于工控网关、上位机、GB28181信令等低延迟场景。本文围绕netIocp示例,拆解SocketAsyncEventArgs核心原理与避坑实践,助你构建稳定高效的长连接服务。

weixin_32864847的博客 315

基于SocketAsyncEventArgs(IOCP)实现的高并发TCP客户端

之前在文章基于SocketAsyncEventArgs(IOCP)的高性能TCP服务器实现(二)——服务端信息接收窗体实现(C#)这篇文章中,我介绍了一个高性能的TCP服务器,目的是接受数千台基于TCP协议的设备发送的信息,并且这些设备只是单向发送,不需要服务器返回信息,设备的信息发送频率在一秒钟一次。服务器端接受到之后,解析信息,然后入库。并且在文章中,我也实现了一个软件窗体,为了有效的检验这个...

aplsc的专栏 2881

C#高性能TCP服务端:SocketAsyncEventArgs与IOCP池化实战

在构建高并发TCP服务端时,异步Socket编程是绕不开的技术底座,而如何高效管理海量连接的内存与回调则直接决定系统吞吐。Windows平台借助IO完成端口(IOCP)将异步操作的完成通知交由内核队列调度,避免了用户态与内核态的频繁切换,配合线程池可显著提升并发处理能力。但仅依赖系统机制还不够,SocketAsyncEventArgs(SAEA)的复用、预分配缓冲区、收发分离等设计,能有效降低GC压力与内存碎片,避免连接数上升后出现句柄暴涨和进程卡死。这些技术广泛适用于网关、长连接服务、游戏服务器网关层及上

weixin_28688385的博客 204

C#高并发Socket实战:完成端口IOCP与SocketAsyncEventArgs性能调优

在高并发网络服务端开发中,I/O模型直接决定系统能支撑的连接规模与吞吐上限。完成端口(IOCP)作为Windows内核提供的异步I/O队列机制,通过完成包派发与线程复用大幅减少上下文切换,是C#服务端承载数万长连接的核心方案。SocketAsyncEventArgs是其托管封装,借助对象池与缓冲区复用降低GC压力,配合接收循环、单飞行发送队列等工程手段,可以构建稳定的大容量Socket网关。该模型适用于即时通讯、物联网接入、推送服务等海量连接场景。以C#完成端口示例为切入点,解析IOCP选型逻辑、Socke

weixin_30444111的博客 319

C# IOCP高并发Socket服务端实战:完成端口模型与SocketAsyncEventArgs详解

在服务端开发中,高并发TCP连接与网络吞吐能力是关键挑战。传统多线程阻塞模型下,每个连接占用一个线程,线程切换与锁竞争导致CPU资源被大量消耗,难以支撑上万连接。完成端口(IOCP)作为Windows内核级异步I/O模型,通过事件投递与完成通知机制,让少量工作线程即可服务海量连接,显著提升吞吐能力。基于C#的SocketAsyncEventArgs是对IOCP的高效封装,结合对象池、内存缓冲管理、心跳检测等工程实践,可构建稳定的大容量TCP服务端。这类方案适用于高并发网关、消息推送、即时通讯等场景,既能解决

weixin_30074763的博客 106

C#高并发Socket实战:IOCP完成端口与SocketAsyncEventArgs详解

在高并发网络编程中,传统的“一连接一线程”模型在数千连接时会面临上下文切换和内存爆炸,而异步IO与完成端口(IOCP)能将等待事件下沉内核,利用线程池高效处理IO完成通知。C#中的SocketAsyncEventArgs基于IOCP封装,支持复用缓冲区与对象,显著降低GC压力,广泛应用于IM服务、物联网接入、网关等需要支撑上万连接的场景。本文从IOCP线程模型原理讲起,逐步拆解C#服务端与客户端实现,并给出压测方法与避坑记录,帮助开发者打造可验证的高并发Socket服务。

weixin_30402231的博客 176
上一篇: 机器学习-随笔(待续)
下一篇: C# 性能优化 List&LinkedList&Dictionary
少年X
博客等级 码龄7年 32粉丝 19原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值