我正在编写客户端应用程序,我想知道是否应该使用Socket类的ReceiveAsync或BeginReceive方法。到目前为止,我一直在使用后者,但是,我发现它似乎对CPU有很大的压力。这是我的接收循环基本上看起来像:
private void socket_ReceiveCallback(IAsyncResult result_)
{
// does nothing else at the moment
socket.EndReceive(result_);
byte[] buffer = (byte[])result_.AsyncState;
// receive new packet
byte[] newBuffer = new byte[1024];
socket.BeginReceive(newBuffer, 0, newBuffer.Length, SocketFlags.None,
socket_ReceiveFallback, newBuffer);
}
现在我一直想知道我在这里做错了什么,因为其他通信应用程序根本不会给CPU带来压力。而且我想知道我是否会更好地使用SocketAsyncEventArgs和ReceiveAsync。
所以这是我的问题:
为什么我的循环如此强调CPU? 我应该使用SocketAsyncEventArgs和ReceiveAsync而不是BeginReceive吗?
答案 0 :(得分:6)
我一直在localhost环回连接上对同步和异步套接字进行基准测试。我的结果是异步版本慢了大约30%。考虑到异步IO现在风靡一时,这对我来说是令人惊讶的。我用了多少线程并不重要。我可以使用128个线程,但同步IO更快。
我认为,原因是异步IO需要更多分配和更多内核模式转换。
因此,如果您不希望有数百个同时连接,那么您可以切换到同步IO。
答案 1 :(得分:1)
要回答这个问题,你必须对你的申请进行分析。 我想知道的是
答案 2 :(得分:1)
BeginReceive
和EndReceive
是在C#5中引入现代async
和await
关键字之前使用的旧的旧式异步模式的残余。
因此,您应该更喜欢在ReceiveAsync
和BeginReceive
上使用EndReceive
来进行异步编程。
对于真正高性能的场景,应使用SocketAsyncEventArgs
。这是专为高性能而设计的,由Kestrel Web服务器使用。
在SocketAsyncEventArgs documentation的备注部分
SocketAsyncEventArgs类是对System.Net.Sockets.Socket类的一组增强的一部分,这些增强提供了可供专业的高性能套接字应用程序使用的替代异步模式。此类是专门为要求高性能的网络服务器应用程序而设计的。应用程序可以单独使用增强的异步模式,也可以仅在目标热点区域(例如,在接收大量数据时)使用
。这些增强功能的主要特征是避免了在大容量异步套接字I / O期间对象的重复分配和同步。当前由System.Net.Sockets.Socket类实现的Begin / End设计模式要求为每个异步套接字操作分配一个System.IAsyncResult对象。
在新的System.Net.Sockets.Socket类增强中,异步套接字操作由应用程序分配和维护的可重用SocketAsyncEventArgs对象描述。高性能套接字应用程序最了解必须持续的重叠套接字操作量。应用程序可以创建所需的任意多个SocketAsyncEventArgs对象。例如,如果服务器应用程序需要始终具有15个未完成的套接字接受操作以支持传入的客户端连接速率,则可以为此目的分配15个可重用的SocketAsyncEventArgs对象。
答案 3 :(得分:0)
我对最大负载做了比较,结果以GB(每秒千兆字节)为单位:
注意:
对于大负载传输,我建议在线程中使用Receive,但是为了在各种连接下获得更好的CPU性能,请使用ReceiveAsync或BeginReceive。