【IT168技术文档】
今天因为一个需要,要研究一下sock的异步性能,就用Reflector看了看。发现在调用的时候.net优先调用的是acceptex的 api,而不是accept api。在msdn里查看了一下这两者的区别:
The AcceptEx function uses overlapped I/O, unlike the accept function. If your application uses AcceptEx, it can service a large number of clients with a relatively small number of threads. As with all overlapped Windows functions, either Windows events or completion ports can be used as a completion notification mechanism.
Another key difference between the AcceptEx function and the accept function is that AcceptEx requires the caller to already have two sockets:
* One that specifies the socket on which to listen.
* One that specifies the socket on which to accept the connection.
it can service a large number of clients with a relatively small number of threads
这句话那是非常的诱人啊!
那我们再来看看什么情况下可以使用这个扩展的Accept呢?
首先在.net的Accept非异步函数里面是不可以调用这个的,只有在异步调用里面才有:BeginAccept方法
其反编译后如下:
下面是CanuseAcceptEx属性的反编译:[HostProtection(SecurityAction.LinkDemand, ExternalThreading=true)] public IAsyncResult BeginAccept(AsyncCallback callback, object state) { if (this.CanUseAcceptEx) { return this.BeginAccept(0, callback, state); } if (s_LoggingEnabled) { Logging.Enter(Logging.Sockets, this, "BeginAccept", ""); } if (this.CleanedUp) { throw new ObjectDisposedException(base.GetType().FullName); } AcceptAsyncResult asyncResult = new AcceptAsyncResult(this, state, callback); asyncResult.StartPostingAsyncOp(false); this.DoBeginAccept(asyncResult); asyncResult.FinishPostingAsyncOp(ref this.Caches.AcceptClosureCache); if (s_LoggingEnabled) { Logging.Exit(Logging.Sockets, this, "BeginAccept", asyncResult); } return asyncResult; }
那个iswinnt还没有找到相关资料,不过看字面意思看起来是平台相关的,是winnt系统应该都可以。private bool CanUseAcceptEx { get { if (!ComNetOS.IsWinNt) { return false; } if (!Thread.CurrentThread.IsThreadPoolThread && !SettingsSectionInternal.Section.AlwaysUseCompletionPortsForAccept) { return this.m_IsDisconnected; } return true; } }
另外检验其他的是否为线程池和是否总是使用完成端口的检测如果不通过的话就检测连接是否还连接着。
其中再各个重载方法中,最重要的是检测IsWinNt选项,要不然就不会执行这个AcceptEx方法。