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方法
其反编译后如下:
[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;
}
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;
}
下面是CanuseAcceptEx属性的反编译:
private
bool
CanUseAcceptEx
{
get
{
if (!ComNetOS.IsWinNt)
{
return false;
}
if (!Thread.CurrentThread.IsThreadPoolThread && !SettingsSectionInternal.Section.AlwaysUseCompletionPortsForAccept)
{
return this.m_IsDisconnected;
}
return true;
}
}
那个iswinnt还没有找到相关资料,不过看字面意思看起来是平台相关的,是winnt系统应该都可以。
{
get
{
if (!ComNetOS.IsWinNt)
{
return false;
}
if (!Thread.CurrentThread.IsThreadPoolThread && !SettingsSectionInternal.Section.AlwaysUseCompletionPortsForAccept)
{
return this.m_IsDisconnected;
}
return true;
}
}
另外检验其他的是否为线程池和是否总是使用完成端口的检测如果不通过的话就检测连接是否还连接着。
其中再各个重载方法中,最重要的是检测IsWinNt选项,要不然就不会执行这个AcceptEx方法。