TCP套接字连接中同步与异步的优势

本文关键字:异步 同步 套接字 连接 TCP | 更新日期: 2023-09-27 18:30:02

我目前正在学习来自java背景的C#。为了让我的脚湿,我决定做一个简单的SMTP邮件应用程序。我很快就了解到C#同时支持同步和异步套接字。

据我所见,使用同步套接字与异步套接字相比并没有真正的优势,因为后者不会阻塞,因此不需要每次都创建一个新线程。使用其中一个似乎也没有明显的开销。

所以我的问题是,使用同步套接字有好处吗?还是在大多数情况下只使用异步套接字更好?

TCP套接字连接中同步与异步的优势

异步IO保存线程。一个线程消耗(通常)1MB的堆栈内存。这是在并发未完成IO操作数量变大时使用异步IO的主要原因。根据我的测量,在进入数千个线程之前,操作系统的可伸缩性不是一个问题。

主要的缺点是,它需要更多的开发工作来使相同的应用程序以相同的可靠性水平工作。

我已经详细地写过这个权衡。另外:我们是否应该默认切换为使用异步I/O?

客观上,建议始终使用异步IO是错误的建议。

任何一种机制都可以工作。主要区别在于,同步意味着要么阻塞一个本来可以做其他有用事情的线程,要么为每个连接指定一个线程。无论哪种方式,这都不是很好。对于很少或只有一个活动连接的简单应用程序,这可能是可以的。

但是,对于任何需要处理大量并发连接的场景,异步API都是唯一能够提供足够性能的API。此外,在任何交互式场景中(即,您必须处理用户输入和输出),异步方法更容易与用户界面集成。现在C#中有了asyncawait,这一点尤其正确。

与您使用的编程语言无关,建议只使用异步套接字是一个糟糕的建议。的确,所有问题都可以使用异步来解决,但并不是所有问题(例如100’000个连接)都可以使用同步连接来解决。但大多数时候,问题往往更简单(<100个连接)。

根据我的经验,(平庸的)程序员往往会迷失在他们使用异步套接字创建的混乱中,而在单独的线程中处理同步套接字是简单、可理解和更易于维护的。在Windows下创建线程成本很高,假设有一个合适的操作系统,它的开销要小得多(在x86/Linux上5 us)。此外,线程不需要1MB的RAM(至少对于本机程序不需要),而是需要几kb的堆栈和状态(寄存器)。

最重要的是,很多人认为同步套接字编程速度较慢,但事实并非总是如此。上下文切换(到其他线程)是有代价的,但异步套接字接口对于操作系统内核来说也不便宜。

一如既往:选择最适合情况的解决方案。