我试图了解 TCP 半开连接和 TCP 半闭连接之间的区别,有人能说出它们到底是什么吗?
答案1
这篇文章详细阐述了半闭连接。有关半开连接,请参阅 KContreau 的正确描述。
什么是半封闭连接?或者:这不是一个错误——而是一个功能!
每个 TCP 连接都由两个彼此独立关闭的半连接组成。因此,如果一端发送 FIN,则另一端可以自由地仅确认该 FIN(而不是 FIN+ACK),这会向 FIN 发送端发出信号,表示它仍有数据要发送。因此,两端最终都处于除 ESTABLISHED 之外的稳定数据传输状态——即 FIN_WAIT_2(对于接收端)和 CLOSE_WAIT(对于发送端)。这样的连接被称为半关闭,而 TCP 实际上是为支持这些场景而设计的,因此半关闭连接是 TCP 的一个功能。
半封闭连接的历史
虽然 RFC 793 仅描述了原始机制,甚至没有提到术语“半封闭”,但 RFC 1122 在第 4.2.2.13 节中详细阐述了这个问题。您可能想知道到底是谁需要这个功能。TCP 的设计者还为 Unix 系统实现了 TCP/IP,并且像每个 Unix 用户一样,喜欢 I/O 重定向。根据 W. Stevens(TCP/IP 说明,第 18.5 节),对 I/O 重定向 TCP 流的渴望是引入该功能的动机。它允许 FIN 确认充当或被转换为 EOF。因此,它基本上是一个允许您在应用程序层上随意创建即兴请求/响应样式交互的功能,其中 FIN 表示“请求结束”。
答案2
其他人对半开半闭连接的描述相当不错是,但半开放连接的想法也经常在它们成为问题的背景下被搜索。
互联网上对于术语“半开”或“半闭”应该代表什么存在争议,但就我而言,术语只是语义上的。有人说“半开”连接是一个“问题”,而“半闭”是一种设计功能,它允许您在文件下载完成之前关闭发送流,从而以半闭状态关闭发送流(如其他用户所述)。
但是,关于另一个……“问题”:打开 TCP 连接需要三次握手,关闭连接则需要四次握手。
TCP 存在一个漏洞,即发送给客户端的最终 FIN 数据包可能会被路由器/网络丢弃,导致连接处于半开状态,而实际意图是完全关闭连接。这种方法和类似的方法一直是流行的拒绝服务攻击类型,因为它们不需要大量带宽,但可能会消耗宝贵的句柄、套接字和线程(具体取决于服务器实现),但由于我们的劣质无线运营商,它们也可能出现在现实世界中,而且频率越来越高。
操作系统已尝试通过限制操作系统中在给定时间内可存在的半开/半闭连接数量以及引入连接可保持半开/半闭状态的最大时间长度来反击半开 DDoS 攻击。不过,就我个人而言,上次检查时,Windows 上的时间限制相当高(如果我没记错的话,是 2 天)。
TCP 保持活动的可选性质进一步加剧了这种情况,如果完全实施,则旨在作为协议级(而不是应用程序级)解决方案来检测死连接/僵尸连接。但是,在设计 TCP 时,带宽比现在要宝贵得多,并且有人担心 TCP 的强制保持活动计时器会太“烦人”。因此,保持活动是可选的,通常不使用,并且不保证根据 RFC1122 由路由器传输。所以...即使您在 TCP 层启用保持活动以尝试检测/处理这种情况,您可能会发现,当您的流量在世界各地传输时,一些路由器会丢弃保持活动数据包...这可能会产生另一种罕见的测试场景。
半开连接对编写基于 TCP 的服务器的程序员来说是一个工程挑战,特别是因为它们可能在高负载时无意中随机出现……并且通常出现在生产服务器上……并且在 Alpha/Beta 测试阶段很难注意到。根据我的经验,我发现在每天处理 250 万个连接的服务器上,每 40,000 个连接中可能出现 1 个半开连接,但这些数字会根据您的流量状况以及服务器和客户端之间互联网每段的流量状况而有所不同。
作为一名工程师,很难追踪那些不经常发生且只在实时部署的服务器上出现的问题,因此在编写 TCP 服务器代码时,尝试模拟这种罕见的连接状态以分析服务器在面对这种情况时会如何反应非常重要。例如,如果您的 TCP 服务器使用静态数量的工作线程,您可能会发现在部署到生产环境时,所有线程都被僵尸连接占用。如果连接需要大量工作内存,那么最终结果可能类似于内存泄漏。等等。
如果没有 100% 可行的保持活动解决方案,TCP 会让用户层决定如何处理半开/关闭连接,因此您的代码必须有一个计划/机制来检测、超时和清理资源,当这种情况发生时……也就是说……假设这是您发明的协议,而不是程序员通常使用的众多(糟糕的)开放标准之一。当然,我指的是 HTTP 等协议,它们完全通过 TCP 运行。在这位程序员看来,这些协议被严重高估了。
意识到 TCP 的弱点以及它在传输 HTTP/Web 流量方面的不幸流行,聪明的公司一直在寻求替代方案。例如,谷歌试验了一种名为 QUIC 的协议,它通过 UDP 传输 HTTP。还有一种名为 TSCP 的开放协议。然而,这些协议都没有得到广泛采用。
通常,我会构建自己的所有服务器,专门使用自己的基于 UDP 的协议进行通信。然而,UDP 比您想象的要复杂得多,而且我感觉我一直在对其进行调整,使其更快、更智能、延迟更低、拥塞更少……但至少我不再需要处理半开连接 ;)
答案3
当 TCP 建立连接时,由于发生了握手,因此认为该连接是有保证的:
- 发起计算机发送连接请求,发送 SYN
- 响应计算机同意该请求,并以 SYN-ACK 回复
- 发起计算机发送确认,回复 ACK
此时连接已建立,数据开始流动。相比之下,UDP 数据包则没有保证,只是希望它能到达目的地。
http://en.wikipedia.org/wiki/Transmission_Control_Protocol#Connection_establishment
正式来说,根据 RFC 的说法,半开 TCP 连接是指已建立连接的一方崩溃,并且未发送连接即将结束的通知。这在今天并不常见。
非正式地,它可以指胚胎连接,即正在建立的连接。
半关闭与上述非官方定义相反。它是一种介于两者之间的状态,计算机正在切断已建立的连接。
答案4
半关闭连接是服务器和客户端的一端打算终止连接时建立的过程。TCP 是一个面向连接的过程,因此每个套接字都是为特定应用程序打开的。在 TCP 中,没有终止应用程序的压力。因此,面向连接的进程通过等待信号来延长终止时间。这在 TCP(连接)中称为半关闭