我目前正在学习来自java背景的C#。为了让我的脚湿透,我决定制作一个简单的SMTP邮件应用程序。我很快就了解到C#提供了对同步和异步套接字的支持。
从我所看到的情况来看,使用同步套接字与异步套接字没有任何实际优势,因为后者不会阻塞,因此每次都不需要创建新线程。使用其中一个似乎也没有明显的开销。
所以我的问题是,使用同步套接字是否有优势,或者在大多数情况下坚持使用异步更好?
答案 0 :(得分:9)
异步IO保存线程。线程消耗(通常)1MB的堆栈内存。当并发未完成的IO操作数量变大时,这是使用异步IO的主要原因。根据我的测量结果,在您进入数千个线程之前,操作系统可扩展性并不是一个问题。
主要缺点是需要更多的开发工作才能使相同的应用程序在相同的可靠性水平下工作。
I have written about this tradeoff at length.另外:Should we switch to use async I/O by default?
建议始终使用异步IO是客观错误的建议。
答案 1 :(得分:7)
这两种机制都有效。主要区别在于,同步意味着阻止一个线程,否则该线程会执行其他有用的操作,或者将线程专用于每个连接。无论哪种方式,这都不能很好地扩展。对于只有少量或只有一个活动连接的简单应用程序,它可能没问题。
但是对于需要处理大量并发连接的任何场景,异步API是唯一能够提供足够性能的API。此外,在任何交互式场景中(即您必须处理用户输入和输出的位置),异步方法更容易与用户界面集成。现在,我们在C#中有async
和await
,这一点尤其如此。
答案 2 :(得分:1)
与您使用的编程语言无关,建议仅异步套接字是一个不好的建议。确实可以使用异步解决所有问题,但是使用同步解决方案不能解决所有问题(例如100'000个连接)。但是大多数时候,问题往往更简单(<100个连接)。
以我的经验,(中等)程序员往往会迷失在使用异步套接字创建的混乱中,而在单独的线程中处理同步套接字则简单,可理解且易于维护。 在Windows下创建线程的成本很高,假设操作系统合适,则开销要少得多(在x86 / Linux上为5 us)。同样,线程不需要占用1 MB的RAM(至少不是本机程序需要),而堆栈和状态(寄存器)则需要几KB。
最重要的是,许多人认为同步套接字编程较慢,但这并不总是正确的。 (到其他线程的)上下文切换是有代价的,但是异步套接字接口对于操作系统内核也不便宜。
一如既往:选择最适合情况的解决方案。