目前,根据我的研究,有三种方法可以异步使用套接字:
.Net 4.5异步示例:Using .Net 4.5 Async Feature for Socket Programming(第二篇文章)
[...]异步:http://msdn.microsoft.com/en-us/library/system.net.sockets.socketasynceventargs.aspx
开始[...]:http://msdn.microsoft.com/en-us/library/5w7b7x5f(v=vs.110).aspx
我对所有选项非常困惑.Net提供了使用异步套接字。我为什么要使用其中一个?有数千个同时连接的性能有什么更好的选择?
答案 0 :(得分:9)
使用SocketAsyncEventArgs
的方法与底层Windows技术(I / O完成端口)最匹配。它们本质上是一个裸机包装器,旨在执行零分配并以不太友好的API为代价提取最高性能。这具有更紧密耦合的代码的缺点,因为它没有实现任何标准Stream
API。其他异步套接字方法都包装了这个。
使用Begin
/ End
对的方法正在使用所谓的异步编程模型(APM)。 APM是.NET的原始异步模型。如果你使用半翘曲的话,很容易写出意大利面条代码,但是一旦你有一些经验,它就会起作用并且相当简单。但是,他们不应该在现代.NET中看到太多用途,因为我们有更容易和更好的表现:
返回Task
的方法正在使用基于任务的异步模式(TAP)。任务是对APM的纯粹升级:它们更灵活,更易于编写,并且通常应具有相同或更好的性能。与语言集成的async
/ await
结合使用后,您可以编写性能卓越且易于理解和维护的代码。
tl; dr 使用Task
方法,除非您有极端性能要求。然后使用SocketAsyncEventArgs
方法。不要使用APM方法。
答案 1 :(得分:5)
有更好的选择可以同时拥有成千上万的表现 连接?
...... 关于Begin [...]的好奇心。如果我有一个MMORPG服务器在哪里 一个连接相互交互以进行位置更新, 动画,效果(基本的MMORPG机制),数字,这会 是“负载很重的服务器”? 200~300个同时连接?
在服务器端,您可以从使用任何异步套接字API(初始/结束样式APM,基于事件的EAP或基于Task
的{{3}}个。这是因为与使用同步API相比,您将阻止更少的线程。因此,更多线程可用于同时向服务器提供其他传入请求,从而提高其可伸缩性。
最有可能的是,您不会看到使用TAP套接字API而不是其APM或EAP类似物的任何性能优势。但是,与APM或EAP相比,TAP API模式更容易开发。与async/await
一起使用时,它会生成更短,更易读且更不容易出错的代码。您将获得自然的伪线性代码流,这是APM回调或EAP事件处理程序无法实现的。如果您找不到基于Task
的正确套接字API,则始终Begin/End
来自Task.FromAsync
APM API Task
(或来自EAP API,请检查{ {3}})。
对于客户端UI应用,可扩展性并不重要,但TAP模式还有另一个好处。通过很少的努力,它有助于使您的UI响应,因为您不会阻止UI线程(通常在等待同步调用的结果时发生)。这不是特定于基于Task
的套接字API,它适用于任何基于Task.Delay()
的API,例如Stream.ReadAsync()
或async/await
。
有关C#中异步编程的一些好的阅读材料,请查看{{1}}标签wiki:
答案 2 :(得分:1)
如果您有机会使用.NET 4.5和async / await,我完全推荐它。
基本上有这些在.NET中进行多线程处理的方法:
第一个是原始线程,您应该避免使用该选项,因为创建线程是一项昂贵的操作。其余的,只是使用ThreadPool的不同方式,这是一个负责维护可用于安排任务的线程集合的工具,产生比第一个选项更好的性能。
使用不同的语法,但对我来说,最清楚的是async / await。我最近创建了WebSocket connector using sockets and asyn/await和the performance is quite good。从技术上讲,async / await并没有给你带来性能提升,但是代码的清晰度将允许你简化应用程序的方法,与基于continuation的混乱代码相比,这可能会带来良好的性能提升。
答案 3 :(得分:1)
首先,您可能希望在MSDN上查看此article,了解.NET中各种异步编程机制之间的差异。
Begin[…]
是第一个使用APM(异步编程模型)的异步套接字实现。它将回调作为其参数之一。虽然与较新的方法相比有些过时,但如果你不介意处理回调和它们可以创建的混乱代码,这种方法很好。由于state
对象,还有一些与此相关的额外开销,在负载很重的服务器上,这可能开始成为一个问题。
[…]Async
使用较新的基于事件的模型,也是一种较轻的实现,可帮助解决Begin[…]
带来的高流量问题。这种方式运行良好,但如果你不小心也可能导致代码混乱。哦,是的,你可以阅读有关here的错误,但除非你正在构建一个性能非常高的软件,否则你可能不会关心它。
基于任务的异步编程(TPL)是最新的机制,在async / await关键字的帮助下,可以提供与[…]Async
相关的大部分(如果不是全部)效率,同时提供更容易理解码。此外,使用Tasks,一次等待多个操作完成要容易得多。重要的是要注意,虽然有几个本机.NET函数实现了TPL并返回Task
,但还没有一个用于Socket操作。有一些如何在线进行此操作的示例,但它需要一些额外的工作。