TCP与UDP(七)

作者: ZhengYaWei | 来源:发表于2017-10-29 16:48 被阅读181次

    TCP/IP 系列文章

    网络基础知识(一)
    TCP/IP基础知识(二)
    物理层(三)
    数据链路层(四)
    IP 协议(五)
    IP 协议相关技术(六)
    TCP与UDP(七)

    一、传输协议层

    1.1 两种传输层协议 UDP 和 TCP

    在 TCP/IP 中能够实现传输功能的,并具有代表性的协议是 TCP 和 UDP 这两个协议。两者都是流协议,你可以把它想象成排水管中的水流。

    TCP 协议能够正确处理丢包问题,保证接收方能够收到数据,与此同时还能够有效利用网络带宽。然而 TCP 协议中定义了很多复杂的规范,因此效率不如 UDP 协议,不适合实时的视频和音频传输。

    UDP 协议是面向无连接的协议,它只会把数据传递给接收端,但是不会关注接收端是否真的收到了数据。但是这种特性反而适合多播,实时的视频和音频传输。因为个别数据包的丢失并不会影响视频和音频的整体效果。

    1.2.1 UDP 首部

    UDP 的首部结构比较简单,如下图所示。



    UDP 首部包含源端口号、目标端口号、包长度和校验和。其中包长度表示 UDP 首部的长度和 UDP 数据长度之和。另外,校验和用来判断数据在传输过程中是否损坏。计算这个校验和的时候,不仅考虑源端口号和目标端口号,还要考虑 IP 首部中的源 IP 地址,目标 IP 地址和协议号(这些又称为 UDP 伪首部)。这是因为以上五个要素用于识别通信时缺一不可,如果校验和只考虑端口号,那么另外三个要素收到破坏时,应用就无法得知。这有可能导致不该收到包的应用收到了包,该收到包的应用反而没有收到。这个概念同样适用于即将介绍的 TCP 首部。

    1.2.2 TCP 首部
    TCP 首部

    毫无疑问,TCP 首部的结构要比 UDP 复杂的多。这也是 TCP 传输速度低于 UDP 的重要原因之一。

    • 序列号:它表示发送数据的位置,假设当前的序列号为 s,发送数据长度为 l,则下次发送数据时的序列号为 s + l。在建立连接时通常由计算机生成一个随机数作为序列号的初始值。

    • 确认应答号:它等于下一次应该接收到的数据的序列号。假设发送端的序列号为 s,发送数据的长度为 l,那么接收端返回的确认应答号也是 s + l。发送端接收到这个确认应答后,可以认为这个位置以前所有的数据都已被正常接收。

    • 数据偏移:TCP 首部的长度,单位为 4 字节。如果没有可选字段,那么这里的值就是 5。表示 TCP 首部的长度为 20 字节。

    • 控制位:改字段长度为 8 比特,分别有 8 个控制标志。依次是 CWR,ECE,URG,ACK,PSH,RST,SYN 和 FIN。在后续的文章中你会陆续接触到其中的某些控制位。

    • 窗口大小:用于表示从应答号开始能够接受多少个 8 位字节。如果窗口大小为 0,可以发送窗口探测。

    • 紧急指针:尽在 URG 控制位为 1 时有效。表示紧急数据的末尾在 TCP 数据部分中的位置。通常在暂时中断通信时使用(比如输入 Ctrl + C)。

    1.2 关于端口号(扩充)

    首先要知道,只有在目标地址、原地址、目标端口号、源端口号以及协议类型(TCP 还是 UDP)这五项内容都一致的时候才被认为是同一个通信连接。


    服务端程序在 UNIX 系统中叫做守护进程。如 HTTP 的服务端程序是 httpd(HTTP 守护进程),而 sshd (SSH 守护进程)。在 UNIX 中并不需要将这些守护进程逐个启动,而是启动一个可以代表他们接收到客服端请求的 inetd(互联网进程)服务程序即可。传输协议 TCP 、UDP 通过接受数据中的目标端口号识别处理程序。

    二、TCP 连接和断开(三次连接,四次挥手断开连接)

    关于 TCP 连接和断开连接的过程,可以参考下图。


    连接和断开连接

    2.1 关于三次握手连接

    三次握手建立连接流程:
    • 1、(客户端):我要建立连接了。
    • 2、(服务端):我知道你要建立连接了,我这边没有问题。
    • 3、(客户端):我知道你知道我要建立连接了,接下来我们就正式开始通信。
    为什么要三次握手,尤其是为何执行第三步?

    一般的思路可能会觉得只要两次握手就可以了,第三步确认似乎是多余的。其实不然,网络是不可靠的,数据包是可能丢失的。假设没有第三次确认,客户端向服务端发送了 SYN 请求建立连接。由于延迟,服务端没有及时收到这个包。于是客户端重新发送一个 SYN 包。假设服务端接收到了第二个 SYN 包,建立了通信,一段时间后通信结束,连接被关闭。这时候最初被发送的 SYN 包刚刚抵达服务端,服务端又会发送一次 ACK 确认。由于两次握手就建立了连接,此时的服务端就会建立一个新的连接,然而客户端觉得自己并没有请求建立连接,所以就不会向服务端发送数据。从而导致服务端建立了一个空的连接,白白浪费资源。但是在有了第三步确认时情况就不一样了,服务端直到收到客户端的应答后才会建立连接。如果客户端接受到一个相同的 ACK 包,这时候它会抛弃这个数据包,不会和服务端再次进行,因此避免了服务端建立空的连接。

    建立连接过程中, ACK 确认丢失后,TCP 协议是如何处理?

    按照 TCP 协议处理丢包的一般方法,服务端会重新向客户端发送数据包,直至收到 ACK 确认为止。但实际上这种做法有可能遭到 SYN 泛洪攻击。所谓的泛洪攻击,是指发送方伪造多个 IP 地址,模拟三次握手的过程。当服务器返回 ACK 后,攻击方故意不确认,从而使得服务器不断重发 ACK。由于服务器长时间处于半连接状态,最后消耗过多的 CPU 和内存资源导致死机。

    正确处理方法是服务端发送 RST 报文,进入 CLOSE 状态。这个 RST 数据包的 TCP 首部中,控制位中的 RST 位被设置为 1。这表示连接信息全部被初始化,原有的 TCP 通信不能继续进行。客户端如果还想重新建立 TCP 连接,就必须重新开始一次握手。

    2.2 关于四次挥手断开连接

    四次挥手断开连接过程:
    • 1、(客户端):我要关闭连接了。
    • 2、(服务端):你那边的连接可以关闭了。
    • 3、(服务端):我这边也要关闭连接了。
    • 4、(客户端):你那边的连接可以关闭了。
    为什么都要执行关闭操作?

    因为连接是双向的,所以双方都要主动关闭自己这一侧的连接。

    ACK 丢失怎么办?

    在第三步中,客户端收到 FIN 包时,会设置一个计时器,等待相当长的一段时间。如果客户端返回的 ACK 丢失,那么服务端还会重发 FIN 并重置计时器。假设在计时器失效前服务器重发的 FIN 包没有到达客户端,客户端就会进入 CLOSE 状态,从而导致服务端永远无法收到 ACK 确认,也就无法关闭连接。

    三、TCP 数据包重发

    丢失数据包再次重发的前提是发送方能够知道接收方是否成功的接收了消息。

    通过序列号和确认应答提高可靠性

    TCP 中,当发送端的数据到达接收端时,接收端会返回一个已收到消息的回执通知,该回执通知叫做确认应答 ACK 。根据 上面对 TCP 首都的分析可知,该 ACK 的值和发送端下次发送数据包在整个发送数据中的序列号相等。更明确的说,ACK 除了告诉发送端已经接收到了当前数据包,还告诉发送端下次发送数据要从那个位置开始发。如下示意图。

    然而,实际情况并不总是那么尽如人意。比如下面这两个问题:
    1、因为网络问题,如果数据包和 ACK 应答都丢失,怎么办?
    此时,发送方如果在一段时间内没有收到 ACK,就会重发数据。
    2、由于网络延迟的存在,接收方收到重复的数据包怎么办?
    通过 TCP 首部中的 SYN 判断这个数据包是否曾经接收过。如果已经接收过,就会丢弃这个包。

    未收到ACK重发过程

    TCP 窗口

    发送端在数据包发出后,直至 ACK 确认返回以前,发送端都无法发送数据,显然是一种浪费,网络利用效率和通信性能就越低。这一问题在 TCP 中通过引入”窗口“的概念得以被解决。

    利用窗口控制提高速度

    ”窗口大小“表示无需等待确认应答ACK返回之前,可以继续发送数据包的最大数量。

    窗口的控制和重发控制

    以下示意图是窗口控制的概念。


    • 在使用窗口控制的过程中,如果是数据包已经到达对端,但是确认应答却没有返回该怎么办?这就是窗口最擅长处理的问题了。假设发送发收到的确认包中的 ACK 第一次是 1001,第二次是 4001。那么我们完全可以相信中间的两个包是成功被接收的。因为如果有没接收到的包,接收方是不会增加 ACK 的。而在没有窗口控制的条件下,发送方就会重发第二个和第三个数据包。如下图所示。


      ACK丢失的情况
    • 在使用窗口控制的过程中,如果是数据包丢失该怎么办?接收端主机如果接收到一个自己应该接受序号以外的数据,此时只会针对在此之前收到数据返回确认应答ACK。如下图,当1001 - 2000 的数据包丢失时,发送端会一直收到系列号为 1001 的确认应发,这个确认应答就好像接收端一直在提醒发送端:“我想接收的是从 1001 开始的数据”。当发送端如果连续 3 次收到同样的确认应答,此时就会针对确认应答序列号发送对应的数据,这种机制被称作高速重发控制。相对于超时重发机制管理更加有效。如下图所示。

    高速重发机制

    相关文章

      网友评论

        本文标题:TCP与UDP(七)

        本文链接:https://www.haomeiwen.com/subject/kiwjuxtx.html