zoukankan      html  css  js  c++  java
  • CCNA-Part5

    传输层主要的作用就是建立端到端的连接。比如电脑的微信的通信,就需要跨越多个网络设备(交换机和路由器)再和微信的服务器建立连接。

    传输层需要具有以下的特点:

    • 会话的多复用:如电脑上开启的多个应用,QQ,微信等,这就意味着同时需要建立多个会话。
    • 识别应用程序:通过端口号,来区分不同的应用程序。
    • 分段:在发送数据时,将数据段分为多个部分进行发送,然后在接收端重新组装这些数据段。(TCP)
    • 流量控制:在发送端和接受端,两者发送和接受的带宽不一致时,可以动态的调整带宽。(TCP)
    • 面向连接:确认对方能接收时再发送(TCP)。
    • 可靠性:保证对方一定能收到数据。(TCP)。

    TCP 和 UDP 就是实现上述特点的协议。

    TCP 报文段

    TCP 连接过程 - 三次握手

    三次握手是个老生常谈的话题,还得在大学时死记硬背这个连接过程,现在想想还蛮好玩的。都说检验一个人是否理解一件事情,就让他给一个从来没有听过的人讲,讲明白了,自然证明也就懂了。其实这就是主动学习和被动学习的体现,大家有兴趣可以查查费曼学习法,讲授给他人,写文章等都是一种主动学习的方式。有点扯远了,回到三次握手的过程,希望能给大家讲清楚。

    在谈起连接过程前,先要对 TCP Header 中这几个字段有一个清晰的了解,在上面的导图也提到了,下面着重强调一下:

    关于 Flag 字段: 该字段是 1 Byte,共 8 位,如果每一位置 1 后,就代表该 TCP 报文开启了对应的功能,其中三次握手共涉及 3 个字段,注意我这里是用大写的表示,并且只有 1 和 0 两种状态:

    • SYN 字段:当置 1 时,表示该报文是请求连接的报文段,用于在 TCP 连接时的第一个连接。
    • ACK 字段:当置 1 时,表示该报文是确认报文,用于表示对方发的请求连接已经收到,这里给予确认。
    • FIN 字段:当置 1 时,表示发送方已经发送完毕,请求关闭连接。

    关于序号字段 seq: 注意这里是小写,共有 4 Byte,32 位。和 IP 层一样,有时当发送的数据超过固定的 MTU 大小时,会将数据包拆成多个小的数据包发送,但数据是有顺序要求,为了保证数据的顺序,就有了该字段 seq,用于表示第一个字节在整个字节流的标号。

    关于确认号字段 ack: 和 seq 一样,4 Byte. 表示对收到的数据进行确认,并告诉发送方接下来期待的序列号是什么。

    最后还需要明确一点,TCP 建立的是双向的连接,因为在端点的另一方可以是发送方也可能是接收方,明确这点非常重要。

    上面看起来比较抽象,一会实际抓包,对照起来看就清晰了。先有个印象,先来分析下 TCP 的连接过程。

    一个 TCP 连接会有三个状态:

    • 建立连接的状态
    • 传输数据的状态
    • 关闭连接的转台

    先看连接状态:

    1. 客户端想要和服务端建立连接:置位 Flag 字段中的 SYN=1,表示请求建立连接。seq = x,表示传送的第一个字节的序号是 x.

    2. 服务端收到客户端请求:

      1. 置位 Flag 字段中的 ACK=1,表示确认跟你连接链接。ack= x + 1,表示前 x 个字节已经收到,期待传送 x+1个字节。
      2. 由于刚才连接过程是客户端到服务端的,同样的,服务端也需要向客户端也发一个请求用于建立连接,这样才是双向连接。正常来说,服务端应该再发一个请求,但由于 TCP 的报头设计,可以将请求功能和确认功能放在一个数据包里,通过 Flag 同时置位 SYN 和 ACK 。这也就是为什么连接时,三次握手而不是四次。
    3. 客户端收到服务端的回复,通过 ack=x+1 知道,服务端收到了 x 字节的数据,期待接受 x+1 字节的数据。通过 SYN=1,seq=y 知道服务端想要和自己连接连接。进而回复 ACK=1,seq=x+1,ack=y+1.

    传输状态:

    如何保证数据的可靠性传输?

    在客户端给服务传输数据时,如果收到 ACK 的报文,则代表服务端确实收到了传递的数据。考虑这样一种情况,客户端向服务端发送了 seq=10 的报文,但却收到服务端 ack=10 的回复。其实这就代表着,存在丢包的情况,服务端并未收到客户端 seq=10 的包。这时服务端会重新发送 seq=10 的报文,也就是说,在客户端只有成功的接收了服务端的 ACK 包,才会继续向下传递。

    如何进行流量控制?

    在 TCP Header 中有一个叫窗口大小的字段。当路由器发送或者接收数据时,会将数据先缓存起来,这个窗口就是对应的缓存区。由于造价的不同,不同的设备对应的缓冲区大小也不一样。考虑这样一种情况,客户端的窗口大小为 3 Byte,但服务端的窗口大小为 2 Byte。这就意味着,服务端只能先缓存 2 Byte 的数据。接着来看下,TCP 是如何进行流量控制的:

    • 第一次,客户端会给服务端直接发送 3 Byte 的数据,注意是通过一个包里面包含 3 Byte 的数据。但由于服务端只有 2 Byte 的缓存空间,第三个 Byte 的内容会被丢掉。
    • 接着服务端会回报,进行 ACK 确认,发送 ack=3,代表接受到了 seq=2 之前的数据。同时还会发送窗口大小 WS(2)告诉客户端自己只有 2 Byte 的缓存空间。
    • 之后客户端只会发送缓存空间为 2 的数据包给服务端。

    考虑一种特殊的情况:

    在服务端收到 2 Byte 的数据时,此时 CPU 的处理变得低效,只从缓冲空间中取出了 1 个字节发送终端。

    这时服务端再给客户端回包时,除了正常回复 ack=x+1 的确认,还会改变窗口大小为 1.,这就意味着告诉服务端,下次给我发包时
    只能接受一个 Byte 的数据。

    实际抓包看一下,这里以访问百度为例子:

    第一次握手:

    结合之前说的:

    • 在 Flag 字段中,SYN 置1,表示这是一个请求连接的报文。
    • seq=0,注意这里的 0 只是抓包软件的相对值,真实值是下面的 ac f7 f8 8b.
    • 源端口为:8548
    • 目的端口为:443

    再看第二次握手:

    同样:

    • 服务端再 Flag 为 SYN 和 ACK 置位,表示该报具有确认和请求连接的功能。
    • ack = ac f7 f8 8c 正好是之前 seq 的大小 +1.
    • seq = 0,其实这里也是相对的位置,真实值为 fd 15 e1 c4,在 ack 的前四字节就是 syn.

    最后第三次握手:

    • 表示客户端确认和服务建立连接,对应 Flag ACK 置位。
    • ack = fd 15 e1 c5, fd 15 e1 c4 + 1.

    断开连接:

    理解了 TCP 连接的过程,再看断开连接就很容易了。一样的,首先要明确,已经建立的连接是双向的连接。如果想要断开的话,自然双方都要发起一个请求。

    而报文内部也大致相同,仅仅是把 Flag 字段中 SYN 换成 FIN 字段,表示想要断开连接。

    同样,假如有客户端和服务端已经建立了连接。

    1. 客户端向服务端发送报文,其中 FIN=1,表示请求断开连接。(断开的是客户端到服务端的连接)
    2. 服务端收到后回包,ACK=FIN+1,表示收到客户端的情况,确认断开。
    3. 服务端再次发送请求,置位 FIN=1,表示要和服务端断开连接。(断开的是服务端到客户端的连接)
    4. 客户端收到后,ACK=FIN+1,表示确认断开和服务的连接。

    这里一定会有疑问,为什么在三次握手中,可以在一个数据包中同时置位 SYN 和 ACK 表示确认和请求连接的过程,等到了断开连接时,就不能这样做呢,而是需要发送两次。

    原因就在于,由于连接是双向的,第1,2步骤表示,客户端已经没有数据发送给服务端了。但这时,服务端可能还有数据正在发送给客户端,等待数据发送完成后。才能进行 3,4 步骤,然后断开服务端到客户端的连接。

    UDP 报文段

    学习了 TCP,再看 UDP 自然就很简单了。

    先看 UDP 的特性:

    • 工作在传输层
    • 执行有限制的差错校验
    • 提供尽力而为的传输
    • 不可能的传输
    • 开销低,传输的效率高

    可以看到,UDP 的 Header 中,仅有源端口,目的端口用于识别应用程序。

    下面来比较一下 TCP 和 UDP:

    关于连接的类型:面向连接/面向无连接

    序号:TCP 由于是可靠传输,所以需要对收到的内容进行 ACK 确认,而 UDP 直接发送,不管对方能不能接受。

    应用场景:TCP 要求可靠的通信,如邮件,FTP,浏览网页,下载等服务。而 UDP 则适合语音,视频,HDCP等等。

    总结

    传输层的作用就是建立端到端的连接,为了实现该功能,一般有两种协议 TCP 和 UDP 可以选择。

    对于 TCP 来说,需要了解并理解三次握手和四次挥手的过程。比较 TCP 和 UDP 的不同,以及适用的场景。

    最后可以用这几个问题检验自己,对应都可以在文章中找到答案:

    1. TCP 在建立连接时,为什么是三次握手而不是四次?
    2. TCP 在断开连接时,为什么是四次而不是三次?
    3. TCP 是如何保证可靠传输的?
    4. TCP 是如何进行流量控制的?
    5. TCP 和 UDP 的区别,以及适用的场景。
  • 相关阅读:
    PHP Session 变量
    PHP Cookie是什么
    PHP 文件上传
    PHP 文件处理
    PHP include 和 require 语句
    Mac pycharm专业版安装以及破解方法
    bzoj3946: 无聊的游戏
    win10 uwp 九幽图床
    win10 uwp 九幽图床
    git无法pull仓库refusing to merge unrelated histories
  • 原文地址:https://www.cnblogs.com/michael9/p/13274132.html
Copyright © 2011-2022 走看看