原文:SocketAsyncEventArgs使用解说

如果在.NET下写过网络通讯的同学应该感觉不陌生了,有很多刚入门的同学很多都认为这东西可以大大提高处理效能还有就是使用上很不适应.其实使用之前最好通过MSDN了解一下,该对象紧紧是Begin End模式的一个增强版本,它的主要作用主要是解决之前异步过程时创建不可复用的异步对象而产生的.主要是在高并发下节省大量对象重分配和同步相关问题,从而实现在高并发吞吐下更少的资源损耗(如果你的应用紧紧是密集通讯那性能提供相对来说是可观一点,但应用还存在其他处理那就不要想着它能有质的改变了).

SocketAsyncEventArgs(SAEA)在.net 2.0 sp1所提供开发人员主要使用它的场景分别是Accept,Send和Receive.在传统的Begin End模式中一般都通过调用Begin方法然后在回调方法中调用End来处理,其实SAEA原理差不多,只是由原来的指定的回调过程变成了完成事件,更重要的一个改变就是SAEA是可以复用的.下面详解一下SAEA的以上几种用法.

主要属性和事件

在使用SocketAsyncEventArgs进行TCP或UDP通讯的时候最常用的几个成员分别是:Buffer,BufferList,BytesTransferred,SocketError,UserToken,BytesTransferred属性,SetBuffer方法和Completed事件。

SocketAsyncEventArgs接收和发送数据都需要设置buffer,一般用SetBuffer方法或设置BufferList。通过Completed来查看完成情况,而在Completed通过SocketError和BytesTransferred结合来判断当前操作是否成功能,如在receive状态当BytesTransferred为零的时候,说明对方已经把连接断开了。

由于SocketAsyncEventArgs是异步操作,在很多情况需要的一些其他信息传递到Completed事件中,这个时候可以通过UserToken属性来解决异步信息传递的问题。

使用注意:SocketAsyncEventArgs同一时间只能进行一个操作,通过Completed来确认当前操作是否完成,如果同步完成是不会触该事件需要自己手动调用处理。

Accept

此方法是管连接接入,一般在写TCP应用的的时候需要用到(UDP下则不需要).

if(!Socket.AcceptAsync(saea))
{
Accept_Process(Socket,saea);
}

在使用的时候一般是采用以上方法,如果是同步完成就手动调用完成处理过程,否则会触发完成事件.所以在构建saea的时候必须绑定Competed事件,也可以通过承继saea类派生OnCompleted方法处理也行.

private void Accept_Process(object sender,SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
//成功
}
else
{
ReleaseSocket(e.AcceptSocket);
}
Accept();
}

可以通过判断SocketError来确定连接接入是否成功,如果方法还要处理一些有可能存在异常的逻辑,那这里最好写上try catch.防止在线程回调过程出现未知异常导致服务关闭的严重问题发生. 在使用SAEA进行Accept的时候其实也可以设置buffer,这个的主要作用是当连接接入后必须收到对方请求的数据才会触发完成事件.

Send

在Socket针对SAEA的Send操作用两个分别是SendAsync和SendToAsync,前者是基于有连接状态常用于TCP,而后者则用于无连接状态的一般发送UDP的时候使用.

if (!mSocket.SendAsync(mSendSAEA))
{
OnSend(this, mSendSAEA);
}

发送方法返回一个布尔值,如果为false则为同步完成需要手动调用完整事件对应的方法;数据的发送情况同样通过SAEA的完成事件来处理.

 private void OnSend(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
{
if (e.SocketError == System.Net.Sockets.SocketError.Success )
{
//成功
}
else
{
// Dispose();
}
}

在完成事件通过SockeError来判断发送是否成功,如果不成功那基本上就说明当前连接出现异常,可以对当前TCP连接断开.实际还有几种状态需要考虑如 IOPending,不过在发关数据的时候是单一投递则不会存在这情况 .在传统的begin,end模式中需要判断发送字节数量的情况,而在SAEA中则不需要.

Receive

接收和发送的原理基本一致.

if (!mSocket.ReceiveAsync(mReceiveSAEA))
{
OnReceive(this, mReceiveSAEA);
}
private void OnReceive(object sender, System.Net.Sockets.SocketAsyncEventArgs e)
{
if (e.SocketError == System.Net.Sockets.SocketError.Success && e.BytesTransferred > 0)
{
//数据接收成功 BeginReceive();
}
else
{
Dispose();
}
}

注意

在Win下SocketAsyncEventArgs绑定Buffer或BufferList都是需要注意,尽可能绑定同一份byte[]的引用,如果不是会导致内部缓存区重新绑定影响性能,Mono下从源代码来看是不会有这情况发生.在一些交流中经常碰到如何用SAEA实现双功,其实网络通讯中只有输入和输出,不存在只是单向的概念,对于SAEA同一时间只能允许一个操作,所以在做应用的时候需要同时接收和发送则可以针对发和收都单独定义个SAEA即可.如果为了更好地利用做个SAEA Pool则相对来说比较好.

SocketAsyncEventArgs使用解说的更多相关文章

  1. 框架设计之ADO.NET Command的ExecuteScalar误用情景及底层解说

    最近下载了点资料,学了学Android,发现Android入门还算简单,从.NET过渡到Android,也就三七十一天的事. 大伙有空也可以学学... 好了,言归正文,那日,有网友发了一个他们公司的数 ...

  2. 【开源】OSharp框架解说系列(1):总体设计及系列导航

    系列文章导航 [开源]OSharp框架解说系列(1):总体设计 [开源]OSharp框架解说系列(2.1):EasyUI的后台界面搭建及极致重构 [开源]OSharp框架解说系列(2.2):EasyU ...

  3. 【开源】OSharp3.3框架解说系列:开发计划与进度

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  4. 【开源】OSharp3.3框架解说系列(7.1):初始化流程概述

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  5. 【开源】OSharp3.3框架解说系列:重新开源及3.3版本新特性

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  6. 【开源】OSharp3.0框架解说系列(6.2):操作日志与数据日志

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  7. 【开源】OSharp3.0框架解说系列:新版本说明及新功能规划预览

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  8. 【开源】OSharp框架解说系列(6.1):日志系统设计

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

  9. 【开源】OSharp框架解说系列(5.2):EntityFramework数据层实现

    OSharp是什么? OSharp是个快速开发框架,但不是一个大而全的包罗万象的框架,严格的说,OSharp中什么都没有实现.与其他大而全的框架最大的不同点,就是OSharp只做抽象封装,不做实现.依 ...

随机推荐

  1. 【ASP.NET Web API教程】2.3.2 创建域模型

    原文:[ASP.NET Web API教程]2.3.2 创建域模型 Part 2: Creating the Domain Models 第2部分:创建域模型 本文引自:http://www.asp. ...

  2. CMDeviceMotion使用

    CMDeviceMotion使用 by 吴雪莹 manager = [[CMMotionManager alloc] init]; ViewController *__weak weakSelf=se ...

  3. 分享一些免费的,开源的邮件server软件

    因为企业的须要,我们非常可能须要架设一个邮件server,微软的Exchange太复杂?GOOGLE出来的又收费!头大了吧,OK,贾芸斐在这里给大家分享推荐几个免费的开源的邮件server软件.希望你 ...

  4. ALV预警灯图标代码

    需要先引用TYPE-POOLS: slis,icon. ICON_LED_GREEN 绿灯 ICON_LED_RED红灯 ICON_LED_YELLOW黄灯

  5. c++ anonymous union,struct -- 匿名联合体和机构体

    c++ anonymous union,struct -- 匿名联合体和机构体 结构体和联合体各自的基本用法不赘述,仅说一下他们匿名时访问的情况.如果是token不同,可以直接跨层访问.例子 #inc ...

  6. hdu 1665 That Nice Euler Circuit(欧拉定理)

    输入n个点,然后从第一个点开始,依次链接点i->点i+1,最后回到第一点(输入中的点n),求得到的图形将平面分成了多少部分. 根据欧拉定理 v_num + f_num - e_num = 2可知 ...

  7. Delphi读写UTF-8、Unicode格式文本文件

    // UTF-8文件写入函数procedure SaveUTFFile(const FileName: string; S: string; WriteHeader: Boolean = True); ...

  8. jquery clone方法

    引用自http://www.w3school.com.cn/tiy/t.asp?f=jquery_manipulation_clone <html> <head> <sc ...

  9. 14.3.2.3 Consistent Nonlocking Reads 一致性非锁定读

    14.3.2.3 Consistent Nonlocking Reads 一致性非锁定读 一致性读 意味着 InnoDB 使用多版本来保护查询一个数据库在当前时间点的快照. 查询看到被事务做出的修改, ...

  10. spring开发基础

    Spring是一个开源框架,它由Rod Johnson创建.它是为了解决企业应用开发的复杂性而创建的.Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途 ...