TCP的认识?TCP 的特性?-问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

TCP的认识?TCP 的特性?

前端问答 2019-12-10 07:32:42 359
网络协议 前端开发
分享到
取消 提交回答
全部回答(1)
  • 前端问答
    2019-12-10 07:33:19
    • TCP 提供⼀种⾯向连接的、可靠的字节流服务
    • 在⼀个 TCP 连接中,仅有两⽅进⾏彼此通信。⼴播和多播不能⽤于 TCP
    • TCP 使⽤校验和,确认和重传机制来保证可靠传输
    • TCP 给数据分节进⾏排序,并使⽤累积确认保证数据的顺序不变和⾮重复
    • TCP 使⽤滑动窗⼝机制来实现流量控制,通过动态改变窗⼝的⼤⼩进⾏拥塞控制

    扩展:

    头部

    从这个图上我们就可以发现 TCP 头部比 UDP 头部复杂的多。

    image.png

    对于 TCP 头部来说,以下几个字段是很重要的

    • Sequence number,这个序号保证了 TCP 传输的报文都是有序的,对端可以通过序号顺序的拼接报文
    • Acknowledgement Number,这个序号表示数据接收端期望接收的下一个字节的编号是多少,同时也表示上一个序号的数据已经收到
    • Window Size,窗口大小,表示还能接收多少字节的数据,用于流量控制
    • 标识符
      • URG=1:该字段为一表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效。紧急数据一定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。
      • ACK=1:该字段为一表示确认号字段有效。此外,TCP 还规定在连接建立后传送的所有报文段都必须把 ACK 置为一。
      • PSH=1:该字段为一表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。
      • RST=1:该字段为一表示当前 TCP 连接出现严重问题,可能需要重新建立 TCP 连接,也可以用于拒绝非法的报文段和拒绝连接请求。
      • SYN=1:当SYN=1,ACK=0时,表示当前报文段是一个连接请求报文。当SYN=1,ACK=1时,表示当前报文段是一个同意建立连接的应答报文。
      • FIN=1:该字段为一表示此报文段是一个释放连接的请求报文。

    状态机

    TCP 的状态机是很复杂的,并且与建立断开连接时的握手息息相关,接下来就来详细描述下两种握手。

    image.png

    在这之前需要了解一个重要的性能指标 RTT。该指标表示发送端发送数据到接收到对端数据所需的往返时间。

    建立连接三次握手

    image.png

    首先假设主动发起请求的一端称为客户端,被动连接的一端称为服务端。不管是客户端还是服务端,TCP 连接建立完后都能发送和接收数据,所以 TCP 是一个全双工的协议。

    起初,两端都为 CLOSED 状态。在通信开始前,双方都会创建 TCB。 服务器创建完 TCB 后便进入 LISTEN 状态,此时开始等待客户端发送数据。

    第一次握手

    客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态。

    第二次握手

    服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入 SYN-RECEIVED 状态。

    第三次握手

    当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入 ESTABLISHED 状态,服务端收到这个应答后也进入 ESTABLISHED 状态,此时连接建立成功。

    PS:第三次握手中可以包含数据,通过快速打开(TFO)技术就可以实现这一功能。其实只要涉及到握手的协议,都可以使用类似 TFO 的方式,客户端和服务端存储相同的 cookie,下次握手时发出 cookie 达到减少 RTT 的目的。

    为什么 TCP 建立连接需要三次握手,明明两次就可以建立起连接

    因为这是为了防止出现失效的连接请求报文段被服务端接收的情况,从而产生错误。

    可以想象如下场景。客户端发送了一个连接请求 A,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求,然后接收数据后释放了连接。

    假设这时候连接请求 A 在两端关闭后终于抵达了服务端,那么此时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入 ESTABLISHED 状态。但是客户端其实是 CLOSED 的状态,那么就会导致服务端一直等待,造成资源的浪费。

    PS:在建立连接中,任意一端掉线,TCP 都会重发 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYN Flood 攻击。遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求。

    断开链接四次握手

    image.png

    TCP 是全双工的,在断开连接时两端都需要发送 FIN 和 ACK。

    第一次握手

    若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

    第二次握手

    B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,此时表明 A 到 B 的连接已经释放,不再接收 A 发的数据了。但是因为 TCP 连接是双向的,所以 B 仍旧可以发送数据给 A。

    第三次握手

    B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。

    PS:通过延迟确认的技术(通常有时间限制,否则对方会误认为需要重传),可以将第二次和第三次握手合并,延迟 ACK 包的发送。

    第四次握手

    A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。

    为什么 A 要进入 TIME-WAIT 状态,等待 2MSL 时间后才进入 CLOSED 状态?

    为了保证 B 能收到 A 的确认应答。若 A 发完确认应答后直接进入 CLOSED 状态,如果确认应答因为网络问题一直没有到达,那么会造成 B 不能正常关闭。

    ......

    总结

    • 建立连接需要三次握手,断开连接需要四次握手
    • 滑动窗口解决了数据的丢包、顺序不对和流量控制问题
    • 拥塞窗口实现了对流量的控制,保证在全天候环境下最优的传递数据
    1 0
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

推荐文章
相似问题