TCP套接字连接中同步与异步的优势
Posted
技术标签:
【中文标题】TCP套接字连接中同步与异步的优势【英文标题】:Advantage of Synchronous vs asynchronous in TCP socket connection 【发布时间】:2014-11-11 11:01:48 【问题描述】:我目前正在学习来自 java 背景的 C#。为了让我的脚湿透,我决定制作一个简单的 SMTP 邮件应用程序。而且我很快了解到 C# 提供了对同步和异步套接字的支持。
据我所见,使用同步套接字与异步套接字并没有真正的优势,因为后者不会阻塞,因此不需要您每次都创建一个新线程。使用其中一个似乎也没有明显的开销。
所以我的问题是,使用同步套接字有什么好处,还是在大多数情况下坚持异步更好?
【问题讨论】:
这一切都取决于具体情况,我会说在 99% 的情况下,您会使用异步,而在罕见的 1% 同步情况下,您希望确保确定发送电子邮件,并且代码块完成并在此之后继续执行程序。此外,如果您为此浇注创建自己的线程,您还将使用同步。 我认为是这样。但我也认为你也可以用异步做同样的事情。还是我错了? @MuhammadHijazi 你可以,你是对的。从功能上讲,使用异步或同步套接字没有区别。 好的,完美!谢谢! 【参考方案1】:异步 IO 节省线程。一个线程(通常)消耗 1MB 的堆栈内存。这是当并发未完成的 IO 操作数量变大时使用异步 IO 的主要原因。根据我的测量,操作系统的可扩展性在您进入数以千计的线程之前不是问题。
主要缺点是需要更多的开发工作才能使相同的应用程序以相同的可靠性水平运行。
I have written about this tradeoff at length.还有:Should we switch to use async I/O by default?
建议始终使用异步 IO 客观上是错误的建议。
【讨论】:
【参考方案2】:任何一种机制都可以工作。主要区别在于同步意味着要么阻塞一个本来可以做其他有用事情的线程,要么为每个连接指定一个线程。无论哪种方式,这都不能很好地扩展。对于具有很少或只有一个活动连接的简单应用程序,它可能没问题。
但是对于需要处理大量并发连接的任何场景,异步 API 是唯一能够提供足够性能的 API。此外,在任何交互式场景中(即您必须处理用户输入和输出的地方),异步方法更容易与用户界面集成。尤其是现在我们在 C# 中有 async
和 await
。
【讨论】:
请注意,为了正确实现,同步 API 意味着侦听器套接字有一个线程,每个客户端连接有 两个 线程。 这取决于应用程序协议。简单的请求/响应协议不需要同时接收和发送,可以在一个线程中处理。 只有在一切完美的情况下。 “简单”的请求/响应协议无法检测到半开状态,至少需要一个计时器来恢复。 对不起...我不明白你的意思。连接的第二个线程如何解决半开问题?除非您尝试发送,否则您仍然不会检测到条件,并且如果协议不要求本地端在收到数据之前发送,则本地端将没有理由尝试。也许您可以提供一个链接,指向更深入的讨论,详细说明您在谈论什么。 对不起,我的意思是协议本身无法检测到半开,无论是同步还是异步。如果它是同步的,那么您需要一个计时器来关闭套接字(从另一个线程),因此无论协议多么简单,都不可能有严格的单线程方法。【参考方案3】:独立于您使用的编程语言,建议仅使用异步套接字是一个不好的建议。的确,所有问题都可以使用异步解决,但并非所有问题(例如 100'000 个连接)都可以使用同步解决。但大多数时候,问题往往更简单(
根据我的经验,(平庸的)程序员往往会迷失在他们使用异步套接字创建的混乱中,而在单独的线程中处理同步套接字是简单、易于理解且更易于维护的。 在 Windows 下创建线程成本很高,假设操作系统合适,开销要少得多(在 x86 / Linux 上为 5 us)。此外,一个线程不需要 1 MB 的 RAM(至少不使用本机程序),而是需要几 kb 的堆栈和状态(寄存器)。
最重要的是,很多人认为同步套接字编程速度较慢,但事实并非总是如此。上下文切换(到其他线程)是有代价的,但异步套接字接口对于操作系统内核来说也不便宜。
一如既往:选择最适合情况的解决方案。
【讨论】:
以上是关于TCP套接字连接中同步与异步的优势的主要内容,如果未能解决你的问题,请参考以下文章