lovegis

导航

异步SOCKET心得

异步SOCKET心得

 

 

将最近在网络通讯项目中对Socket使用的一些经验总结如下。

 

 

1.         不要在异步完成方法中进行耗时的调用。

 

这里的异步完成方法在.NET FRAMEWORK 2.0对应于异步操作的回调方法,以Socket.BeginSend方法为例如下。

public IAsyncResult BeginSend(

      byte[] buffer,

      int offset,

      int size,

      SocketFlags socketFlags,

      out SocketError errorCode,

      AsyncCallback callback,

      Object state

)

参数“callback”是一个委托,代表在发送完毕后,在IOCP线程中将要调用的回调方法。

 

.NET FRAMEWORK 2.0 SP1SP2中添加了一个类SocketAsyncEventArgs,它的事件Completed同样是在IOCP线程中触发的,用于在IOCP线程中处理异步操作的完成。

 

后文所说的异步完成方法就对应callback委托和Completed事件。

 

下面说为什么不能在异步完成方法中进行耗时的操作。

 

IOCP线程开启的个数和CPU核数有关(经过试验),默认情况下开启的IOCP线程数据和CPU数目一致。即时调用了ThreadPool.SetMaxThreadsThreadPool.SetMaxThreads方法 ,单核CPU上只默认开启一个IOCP线程,双核则开启两个。当然开启的IOCP线程数也可能超过CPU个数。这发生在已开启的IOCP线程处于阻塞状态(不会分配CPU时间),只有当所有已开启的IOCP线程处于阻塞状态时才会有开启新的IOCP线程。

 

可以确定在任意时刻可执行(为处于休眠状态)IOCP线程的数目都不会超过CPU核数。所有异步操作完成后都在IOCP队列排队,等待取出后调用异步完成方法。

 

 

2.         异步建立连接。

 

当远程端口未建立监听时,同步建立连接(Connect)将会很耗时、尤其是当远程主机并未开启时。

 

 

3.         同步接受(Accept)连入的套接字。

 

异步接受(AcceptAsyncBeginAccept)连入的套接字,接受完成后要在IOCP队列排队,前面说过所有的异步操作完成后都要在IOCP队列排队,可能接受完成前面已经有很多需要处理的完成操作,可能会很耗很多时间。这样就造成了监听队列中套接字不断增加,达到最大值后,便无法连入新的套接字。造成远程主机连接失败。在一个循环中同步接受连入的套接字,可以尽快的从监听队列中取出连入的套接字,加快对连接的响应。

      

posted on 2009-06-03 11:48  lovegis  阅读(1049)  评论(1编辑  收藏  举报