.NET异步套接字:在这种情况下SocketAsyncEventArgs在Begin / End上的任何好处是什么?

时间:2011-08-30 00:59:58

标签: .net sockets asynchronous socketasynceventargs

Socket有这些new async methods since .NET 3.5用于SocketAsyncEventArgs(例如Socket.SendAsync()),它们使用IO完成端口并避免需要继续分配。

我们使用一个简单的界面创建了一个名为 UdpStream 的类 - 只需 StartSend 已完成事件。它分配两个SocketAsyncEventArgs,一个用于发送,一个用于接收。 StartSend只是使用SendAsync调度消息,并且每秒调用大约10次。我们在接收SocketAsyncEventArgs上使用Completed事件,并在处理完每个事件后,我们所有的ReceiveAsync都会形成一个接收循环。同样,我们每秒大约收到10次。

我们的系统需要支持 500 这些 UdpStream 对象。换句话说,我们的服务器将与500个不同的IP端点同时通信。

我在MSDN SocketAsyncEventArgs示例中注意到它们分配了N x SocketAsyncEventArgs,一个用于您希望一次处理的每个未完成的接收操作。我不清楚这与我们的场景究竟有什么关系 - 在我看来,也许我们没有得到SocketAsyncEventArgs的好处,因为我们只是为每个端点分配一个。如果我们最终获得500个SocketAsyncEventArgs,我认为我们将无法获益。也许我们仍然可以从IO完成端口获得一些好处?

  • 此设计是否正确使用SocketAsyncEventArgs 缩放到500?

  • 对于我们使用单个“UdpStream”的情况,有 使用SocketAsyncEventArgs与使用旧的Begin / End API相比有什么好处?

2 个答案:

答案 0 :(得分:10)

  

在我看来,也许我们没有得到SocketAsyncEventArgs的好处,因为我们只是为每个端点分配一个。如果我们最终获得500个SocketAsyncEventArgs,我认为我们将无法获益。

仍然有很大的好处。

如果您使用APM模式(开始/结束方法),则每个BeginSend和每个BeginReceive都会分配一个IAsyncResult实例。这意味着有一个完整的类/对象分配大约每秒发生10,000次(500 * 10 [发送] + 500 * 10 [接收])。这会给系统带来巨大的额外开销,因为它会增加很多GC压力。

切换到针对高性能网络应用程序的新建议方法,您需要为每个方法调用预分配SocketAsyncEventArgs实例(500)和重用它们,从而消除创建的GC压力在这些行动中。

答案 1 :(得分:6)

  自从.NET 3.5与SocketAsyncEventArgs(例如Socket.SendAsync())一起使用时,Socket有了这些新的异步方法,因此它们使用IO完成端口并避免需要继续分配,从而有利于它。

Begin / End方法也使用IO完成端口。

  

对于我们使用单个“UdpStream”的情况,使用SocketAsyncEventArgs与使用较旧的Begin / End API相比有什么好处?

imho你应该坚持你所知道的,因为你会让产品更快地运行起来。但我也会创建一个严格的IO处理类来处理传输。如果传输性能被证明是瓶颈,则可以更轻松地切换到新模型。