C# 尽管缓冲区空间很大,Socket.BeginSend无法同步完成

C# 尽管缓冲区空间很大,Socket.BeginSend无法同步完成,c#,sockets,asynchronous,C#,Sockets,Asynchronous,为什么Socket.BeginSend异步化的速度如此之快且不可预测?我知道它应该是异步的,但它也可以立即完成,在这种情况下设置了IAsyncResult.CompletedSynchronously。我希望在8KB发送缓冲区被填满之前,CompletedSynchronously将为真。下面的测试用例(为简洁起见去除了清理代码)演示了BeginSend在仅缓冲6个字节的数据后,在(通常)第三次迭代中是异步的: TcpListener侦听器=新的TcpListener(IPAddress.Any

为什么
Socket.BeginSend
异步化的速度如此之快且不可预测?我知道它应该是异步的,但它也可以立即完成,在这种情况下设置了
IAsyncResult.CompletedSynchronously
。我希望在8KB发送缓冲区被填满之前,
CompletedSynchronously
将为真。下面的测试用例(为简洁起见去除了清理代码)演示了
BeginSend
在仅缓冲6个字节的数据后,在(通常)第三次迭代中是异步的:

TcpListener侦听器=新的TcpListener(IPAddress.Any,35001);
listener.Start();
套接字客户端=新套接字(AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp)
Connect(新的IPEndPoint(IPAddress.Loopback,35001));
套接字服务器=侦听器。AcceptSocket())
for(int i=1;i sent=true,null);
Assert.IsTrue(result.CompletedSynchronously,//在第三次迭代时失败
Format(“迭代{0}时异步”,i));
Assert.IsTrue(已发送);
client.EndSend(结果);
}
当它变为异步时,确切的迭代有点随机。当这个过程开始时,它是3。之后,所有新插座都是1。我偶尔也看到其他数字。我知道8KB套接字发送缓冲区在那里,因为
socket.send
(带
socket.Blocking=false
)在8KB左右停止

方法
Socket.SendAsync
的行为类似,只是它总是异步完成(即不尝试直接写入缓冲区)。看我的


出于性能原因,我需要
BeginSend
大部分是同步的(异步回调比较慢)。更不用说不可预测性会破坏我的底层通信代码的单元测试和基准测试。

这个问题通常没有意义。现代处理器生成数据的速率比通过网络发送数据的速率高出两个数量级。获得同步发送的唯一方法是人为延迟BeginSend调用。BeginSend的要点是不要这样做。@Hans注意到我正在循环中调用
Socket.EndSend
。这意味着上一次发送已经完成。无需等待,因此无需异步完成。@Hans我也不太确定处理器的速度。我以前的基准测试清楚地表明,使用
Blocking=false的
Send
BeginSend
快得多。这可能是由于针对大量IP的许多小数据包的开销造成的。当然,它更快,异步的要点是,您可以做一些其他的事情,而不会有一个线程不做任何有用的事情。但是异步的开销不是零。快速调用EndSend()是没有意义的,只需调用非异步Send()即可。@Hans该示例只是问题的简单演示。在我真正的应用程序中,我当然会同时处理同步和异步完成。这个问题更多的是关于理解.NETAPI,即为什么它坚持异步回调,为什么它不可预测。