重新认识 TCP 三次握⼿ 和 四次挥⼿ |
您所在的位置:网站首页 › msl是什么牌子的包 › 重新认识 TCP 三次握⼿ 和 四次挥⼿ |
前言
欢迎关注公众号《熊的猫》 ,本公众号会定期分享技术干货! HTTP 协议 和 WebSocket 协议都是基于 TCP 协议,那么自然少不了对 TCP 协议的探究,当然本文不会涉及和 TCP 流量控制、拥塞控制、可靠性传输 等⽅⾯内容,因为这些部分涉及到的内容不算少,这里主要是针对大家常见的 TCP 连接 和 断开 进行探讨。 在开始正文之前,你可尝试着回答一下面给出的问题: 为什么不直接使用 TCP 协议,反而要使用 HTTP 协议 和 WebSocket 协议? 为什么需要 TCP 协议? TCP 握手 为什么需要 三次 握手建立连接?不能是 两次 或者 四次 吗? TCP 挥手 为什么需要 四次 挥手断开连接?不能是 三次 或者 五次 吗? 为什么不直接使用 TCP 协议?我想应该有不少人也有一样的问题,那就是我们使用的 HTTP 协议 和 WebSocket 协议都是基于 TCP 协议,那么到底是什么原因使得我们不能直接使用 TCP 协议,反而要使用一个 二开 的东西呢? 首先,TCP 也作被称作为 传输层协议 (通常被称为 TCP/IP 协议),TCP 协议支持两个进程通过 三次握手 建立稳定的通信信道,发送 字节流,并保证可靠传输。 说白了,TCP 作为 传输层协议,其主要功能就是 传输数据,那么问题就来了,它是可以传输数据,但是没有任何规范表明接收端要 如何接收 或 如何识别 数据信息,那么这数据虽然可以发送,但是没有意义。 这就好像,A 和 B 两个人打算进行交流,A 用自己的地方语言说,B 也用自己的地方语言说,结果两个人都没听明白,于是他们决定用 普通话 来作为互相交流的标准。 回过头来说,HTTP 协议建立在 TCP/IP 协议之上的意思是,TCP/IP 协议 让 收/发 双方支持并提供传输数据的能力,而 HTTP 协议定义了 接收/发送 数据的规范。 换句话来说,传输层协议 如果不用作用到 应用层, 那么这样的 数据传输 自然也就没有任何意义,因此应用层也有自己的协议 HTTP、DNS、FTP、SMTP 等等,当然也可以自己定义去应用层的协议。 TCP 是 ⾯向连接的、可靠的、基于字节流的 传输层通信协议. ⾯向连接:即 ⼀对⼀ 连接,不能像 UDP 协议可以⼀个主机同时向多个主机发送消息,即 ⼀对多 可靠的:TCP 可以保证⼀个报⽂⼀定能够到达接收端,⽆论⽹络链路中出现了怎样的链路变化 字节流:消息是 没有边界的,即⽆论多大de消息都可以进⾏传输 并且消息是 有序的,当 前⼀个 消息没有收到的时候,即使它先收到了后⾯的字节,那么也不能扔给应⽤层去处理 对 重复的 报⽂会⾃动丢弃 PS:MAC 头部是以太⽹使⽤的头部,它包含了接收⽅和发送⽅的 MAC 地址等信息 通常都会说 TCP/IP 协议,那么就得先来简单了解下 IP 协议,上面的图中表明 IP 协议是处于 网络层. TCP 和 IP 层都可以进行分片处理,TCP 层是按照 MSS 进行分片,而 IP 层是按照 MTU 进行分片. 说到这个就得先了解 MTU 和 MSS: MTU :⼀个⽹络包的最⼤⻓度,以太⽹中⼀般为 1500 字节 MSS :除去 IP 和 TCP 头部之后,⼀个⽹络包所能容纳的 TCP 数据的最⼤⻓度简单的说,就是⽤于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括 Socket、序列号 和 窗口⼤⼩ 就称之为连接. Socket:由 IP 地址和端口号组成 序列号:⽤来解决乱序问题等 窗⼝⼤⼩:⽤来做流量控制因此,建⽴⼀个 TCP 连接是需要客户端与服务器端达成上图中的三个信息共识。 如何唯⼀确定⼀个 TCP 连接呢?TCP 四元组 可以唯⼀的确定⼀个连接: 源地址 源端⼝ ⽬的地址 ⽬的端⼝TCP 是⾯向连接的协议,所以使⽤ TCP 前必须 先建⽴连接,⽽建⽴连接是通过 三次握⼿ 来进⾏的. 相信大多数的回答应该都是:“因为三次握⼿才能保证双⽅具有接收和发送的能力”,当然这回答是没问题,但是没有说出主要的原因. 三次握⼿的原因: 三次握⼿才可以 阻⽌重复历史连接的初始化 —— 主要原因 三次握⼿才可以 同步双⽅的初始序列号(SeqNum) 三次握⼿才可以 避免资源浪费 原因一:防⽌旧的重复连接初始化造成混乱客户端连续发送多次 SYN 建⽴连接的报⽂,在⽹络拥堵情况下: ⼀个 旧 SYN 报⽂ ⽐ 最新的 SYN 报⽂ 早到达了服务端 —— client --> server 此时服务端就会回⼀个 SYN + ACK 报⽂给客户端 —— server --> client 客户端收到后可以根据⾃身的上下⽂,判断这是⼀个历史连接(序列号过期或超时),那么客户端 就会发送 RST 报⽂给服务端,表示中⽌本次连接 —— client --> server如果是 两次握⼿连接,就不能判断当前连接是否是历史连接,三次握⼿ 可以保证客户端因有⾜够的上下⽂来判断当前连接是否是历史连接,可以决定第三次报⽂时,是发送 ACK 报文,还是 RST 报文 原因二:同步双⽅初始序列号,保证可靠传输TCP 协议的通信双⽅,都必须维护⼀个 序列号, 序列号是可靠传输的⼀个关键因素: 接收⽅ 通过 序列号 可去除重复的数据 接收⽅ 可根据数据包的 序列号按序接收 可标识发送出去的数据包中, 哪些是已经被 接收方 收到的,哪些属于丢失的 如果非要进行四次握手,无非就是服务端将 ACK 报文 和 SYN 报文 分别发送给客户端,但由于这两步可以被优化成⼀步,所以就成了 三次握⼿,也就是说,四次握手也可以但是没必要.假设只有 两次握⼿,当客户端的 SYN 请求连接在⽹络中阻塞,客户端没有接收到 ACK 报⽂,由于 TCP 的超时重传机制,会重新发送 SYN 请求,但此时因为没有 第三次握⼿,服务器不清楚客户端是否收到了⾃⼰发送建⽴连接的 ACK 确认报文,所以每收到⼀个 SYN 请求就只能先主动建⽴⼀个连接. 根据上面的情况会造成什么问题呢?如果客户端的 SYN 阻塞了,重复发送多次 SYN 报⽂,那么服务器在收到请求后就会建⽴多个冗余的⽆效链接,造成不必要的资源浪费. TCP 四次 握手/挥手服务端 和 客户端 双方都需要 ⼀个 FIN 和 ⼀个 ACK,因此通常被称为 四次挥⼿. 为什么挥⼿需要四次? 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端 不再发送数据 了,但 还能接收数据 服务器收到客户端的 FIN 报⽂时,先返回 ACK 应答报⽂,⽽服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报⽂给客户端来表示同意现在关闭连接简单的说,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN ⼀般都会分开发送,从⽽⽐ 三次握⼿ 导致多了⼀次,即 四次握手. 为什么 TIME_WAIT 等待的时间是 2MSL?主动关闭连接 的才有 TIME_WAIT 状态. MSL (Maximum Segment Lifetime),报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这个时间的报⽂将被丢弃. TIME_WAIT 等待 2 倍的 MSL,⽐较合理的解释是: ⽹络中可能存在来⾃ 发送⽅ 的数据包,当这些 发送⽅ 的数据包被 接收⽅ 处理后⼜会向 发送方 发送响应,即⼀个来回需要等待 2 倍的 MSL 时间. 为什么需要 TIME_WAIT 状态?需要 TIME-WAIT 状态的主要原因: 防⽌具有相同 四元组 的 旧 数据包被收到,产⽣数据错乱等问题 保证 被动关闭连接⽅ 能被正确的关闭,即保证最后的 ACK 能让 被动关闭⽅ 接收,使其正常关闭 最后欢迎关注公众号《熊的猫》 ,本公众号会定期分享技术干货! 网络相关的内容比较多,也是一环套一环,因此,这里没有展开太多,否则篇幅就很长了,感兴趣的可以自行学习,希望本文对你有所帮助!! 文中的图示从 图解网络 中进行借鉴。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |