从运输层到网络接口层发生了什么?

从运输层到网络接口层

创建套接字

  1. 协议栈的内部结构由上到下

    • 应用程序(网络应用程序 Socket );

    • 操作系统 协议栈 TCP、UDP、IP(ICMP,ARP))驱动程序(网卡驱动程序等);

    • 硬件(网卡)

  2. 一般收发时间比较短的用的是UDP连接比如DNS查询视频流;需要稳定的是TCP来传输,比如邮件服务web访问

  3. IP 是用来控制网络包的收发状态,数据会切成一个一个的包。

    • ICMP告知传输过程中产生的错误以及控制信息
    • ARP 用来根据IP地址获取对应的 MAC 地址
  4. 套接字: 通信的控制信息,比如在 windows 系统的 netstat -ano

    • 创建套接字会形成记录,包括:
      • PID
      • 本地IP : 本地端口
      • 目的IP : 目的端口
      • 当前状态(listening| established)
      • 协议(TCP|UDP)。
        其中 0.0.0.0 表示的是 已经连接但没有进行通信。
  5. 客户端调用 Socket 的时候 ① 先在内存中开辟一个空间来存储信息;② 存入信息.

    • 描述符 = socket(地址,端口,…) ;

    • 连接;

    • write() 发送;

    • 接收 len = read();

    • close();

      个人理解:这里的描述符就是指的JAVA中的变量,所指向的是内存中刚开辟的这段空间的首地址。

连接服务器

  1. 什么叫做连接:

    • 创建套接字后应用程序将会调用 connect 组件;
    • 双方开始交换各自的控制信息;
    • 客户端的协议栈需要知道向谁发送消息(服务端的 IP 和 端口);
    • 链接时,向服务端明确自己的IP和端口(服务端才知道我这是在跟谁在连接);
    • 最后在客户端地方形成一个缓冲区来保存数据。
  2. 关于控制信息:

    • 客户端和服务器相互联络时交换的控制信息。

      • TCP头部格式:

        发送端口 接收端口 序号 ACK 数据偏移量 保留 控制位 窗口 检验和 紧急指针 可选字段
      • 一个完整的数据包:

        • 以太网和IP控制信息

        • TCP控制信息

        • 数据块

    • 保存在套接字的控制信息:主要明确下一步继续做的事情

      • 应用程序传递来的信息;
      • 从服务端 | 通信对象那里接收过来的信息
      • 收发数据操作的执行状态。

收发数据

  1. 将HTTP消息给协议栈。是将调用完成connect之后进行数据发送的阶段。

    • 协议栈不会关心数据,因为数据是一些长度一定的二进制;

    • 有两种发送的方式:

      • 马上发送(网络包小,效率低)

      • 缓冲区满再发送(延迟高)

    • 判断长度:

      • MTU 最大传输单元(以太网:一个网络包的最大的长度是1500个字节);

      • MSS最大报文长度选项:去掉头部后,一个网络包所能容纳TCP数据的最大长度。

    • 组成:

      报头/起始帧分界符 MAC头部 IP头部 TCP头部 数据 FCS(帧校验位)
  2. 对于数据较大的包:只要超MSS的长度,以MSS为单位分割并且每一个添加 TCP头部,标记,端口等。

    其中标记是来说明当前的数据包是这个数据的第几个包。

  3. 通过 ACK 确认是否收到数据包。(TCP的工作便是 确认收到数据包并且对没有收到的数据包重新发送)

    • 客户端在发送的时候会产生一个随机的初始值 => 作用:表示包的标号从这里开始;
    • 发送的数据长度 = TCP网络包的长度 - TCP头部的长度;
    • 接收方的确认响应:当前数据的所有长度和写入了 ACK号的 TCP头部的返回;

    大体流程:

    • 客户端数据+初始值发送给服务器;
    • 服务器计算ACK返回给客户端。
  4. 根据网络包的平均往返时间来调整 ACK 等待的时间。

    • 产生的原因: 网络包的传输的速率不同,比如局域网下通常是几毫秒,互联网情况下几百毫秒也有可能;
    • 当时间过短,以为丢失,数据包重传之后ACK才回来;当时间过长,发生了数据丢包不能够及时的重传;
    • 如何自动调整时间: TCP在发送数据的时候,实时侦测 ACK 的返回时间,自动调整等待的时间。
  5. 窗口管理 ACK 号

    • 窗口是接收方的缓冲区;
    • 收到数据后先进缓冲区,然后计算ACK的值等并把数据发送给应用程序;
    • 滑动窗口:等待ACK返回的同时直接发送数据(TCP调优参数);
  6. ACK 与 窗口合并

    • 什么时候发送窗口的大小:当接收方把数据发送给应用程序的时候
    • 需要连续发送ACK窗口大小的时候,仅需要发送最后一次就好
    • ACK 和 窗口的大小可以在一个包里面一块发送。
  7. 接收HTTP的响应(服务端)

    • 检查收到的数据块和tcp 头部的内容

    • 判断数据是否丢失(根据标号);

    • 返回 ACK;

    • 暂时放入缓冲区;

    • 还原数据(去掉头部);

      交给应用程序
      交给应用程序两步走:

      • 先将数据复制到对应应用程序指定的内存的地址将控制权转移给应用程序
      • 同时向客户端发送窗口更新,告知客户端窗口当前的大小。

从服务器断开并删除套接字

  1. 数据发送完毕后就开始断开连接

    • 应用程序判断数据发送完毕后就开始断开连接;
    • 数据发送完成的一方会发起断开过程;
    • 过程:
      • 调用 Socket 的close程序;
      • 生成含有断开信息(FIN 设置为 1 )的TCP头部;
      • 委托IP模块发送数据;记录相关信息;
  2. 删除套接字

    • 删除套接字的时候会有一个等待的时间

      • 客户端发 FIN,服务端回 ACK;
      • 服务端发 FIN,客户端回 ACK
      • 这样才是真正的结束。
    • 客户端给服务端发送 FIN 的时候 服务端回了 ACK了。

      • 如果客户端直接删除了套接字,释放了本地的资源(端口)
      • 同时一个新的应用程序刚刚占用该端口创建了套接字
      • 马上就收到了来自服务端的 FIN 的数据包了,只能执行断开操作。
        再回想整个过程:1)服务端创建套接字;2)客户端创建套接字并发起连接请求;3)客户端与服务端连接调用 connect;4) 双方开始进行数据的收发;5)断开连接并且删除套接字。

IP与以太网的包收发操作

  1. 包的基础知识

    • 网络包是由头部和数据组成的。头部包含目的地址等控制信息,头部的后面就是数据。
    • 发送方的网络设备创建包,添加上控制的头部和要发送的数据后发送给最近的转发设备,转发设备根据头部中信息和转发设备中的表确定接下来去哪里。
    • 对于TCP/IP在传输的过程中
      • IP协议根据IP头部目的地址判断下一个IP转发设备的位置(但IP协议不会进行数据传输);
      • 子网中以太网协议(MAC头部)将包传输到下一个转发设备。
        在这里以太网是可以更换的,比如光纤,无线局域网等,IP更加灵活。
  2. 包收发操作概览

    • 包在收发的过程中

      • TCP模块先在数据块的前面加上TCP头部,然后整体传递给IP模块
      • 同时TCP模块还要告诉IP模块将数据发给谁(目的地址)
      • IP模块收到后 添加上IP头部和MAC头部。
    • IP头部是确定的是发往目的地址所需要的控制信息(主要是 目的IP地址),这个在传输的过程中不会变化;

    • MAC头部包含通过以太网局域网传输到最近路由器的控制信息 (主要是MAC地址),会随着路由每次更新寻找下一个路由的位置。

    • 对于IP模块来说,TCP和数据对它自己都是一样的,仅仅当作数据来看待。

      所以无论是发送的控制包还是数据包,IP对各种类型的包的收发操作是一致的。

      它仅仅负责将包从源地址发送到目的地址,对丢包乱序等一概不知。

  3. 生成包接收方IP地址的IP头部

    • 先看IP模块的目的地址来自于哪里?

      • IP模块的地址来源于TCP模块

      • TCP模块的地址来源于应用程序,

        所以IP生成的包的目的地址是根据应用程序给的目的地址来确定的。

    • IP头部的格式

    从运输层到网络接口层发生了什么?

    • 进一步:

      • 版本号:v4 / v6
      • ID号一般是包的序号;
      • 分片偏移量:当前包内容为整个数据的第几个字节;
      • 协议号 TCP:06UDP:11ICMP:01
    • IP地址对应的并不是计算机而是网卡,是网卡的地址

      在家庭中一般只有一个网卡所以日常生活中简单说IP对应着计算机。

  4. 生成以太网的MAC头部

    • 为什么存在 MAC 头部? 在TCP/IP里面通过目的IP地址来确定目标在哪里但对于以太网中是根据MAC头部来确定目的地在哪里。

    • MAC地址的头部

      从运输层到网络接口层发生了什么?

    • 以太类型中

      • 0000-05DC 表示 IEEE802.3
      • 0800 表示 IP协议
      • 0806 表示 ARP协议
      • 08DD 表示 IPV6 协议
    • MAC 地址是写入到 网卡的ROM 中,那么为什么还会存在软MAC?

      • 是因为网卡在初始化的时候是将ROM中的地址写入到内存中,应用程序在读MAC地址的时候是从内存中获取的而不是ROM中且权限是读写。
  5. 通过ARP查询目标路由的MAC地址

    • ARP 址解析协议:原理是使用广播的方式问这个IP地址是谁的,只要由应答的就把他的MAC地址拿过来并写入到MAC地址头部。
    • 为了提高速度就会有ARP缓存的产生,ARP缓存一般在几分钟内会全部删除,重新执行一次ARP查询。
  6. 以太网的基础知识

    • 以太网的基础架构:
      • 10BASE5 以太网原型< 相当于直接连接到主干网 | 收发器以及收发器的网线 >;
      • 10BASE-T 中继式集线体的变体< 相当于多个终端连接到一个集线器上,主干网一根线与集线器相连 | 双绞线 >;
      • 交换式集线器的结构<这里的终端连接到交换机上>。
    • 10BASE5 以太网原型,某个设备发送信号,该网络下所有的都能收到,为了确定谁是接收者,在信号的头部添加信息,就是接收者的地址。
    • 通过目的MAC确定向谁发送;通过源MAC 知道谁发出来的;通过以太类型判断装了什么样的数据。
    • 集线器与上面的大体类似,但交换机不同,最大的改变是 数据仅是会从源MAC到目的MAC,不会进行广播。
  7. 将IP包转换成电或者光信号发送出去

    • IP 包在内存中仅仅是一串数字信息,只有将其转换成光或者电信号才可以进行传输

    • 负责这个工作的是 网卡。协议栈生成IP包 --> 网卡驱动程序 --> 扩展总线接口 --> 网卡。

    • 网卡的组成,由上到下

      • 缓冲区(缓冲数据)

      • MAC(控制碰撞检测,重发等)

      • PHY(MAU)发送和接收信号的电路、

      • RJ-45 接口

      • ROM 用来存储全球唯一的MAC地址

    • 网卡中的MAC地址是驱动程序在初始化的时候给MAC模块设置的MAC地址,所以MAC地址有两个来源,一个是网卡本身的ROM,一个是来自命令或者配置文件。

  8. 给网络包再加三个控制数据

    • IP包先到网络驱动,驱动找到网卡将数据存放在缓存区,接着调用网卡的MAC模块,增加三个控制数据:
      • 报头
      • 起始分界符
      • FCS
    • 报头的作用是确定传输的时机;起止分界符是用来确定帧的起始位置;
    • 包在发送的时候是将数据和时钟周期叠加在一起发送,然后根据固定的时钟频率再还原成对应的比特。如果判断时钟的周期,这边是报头的作用;
    • 末尾的FCS(帧校验序列)32比特序列,通过算法将数据包从头到尾算一遍,接收方根据其判断是否发生了变化。这里与 CRC (循环冗余检验) 效果类似,发生错误就会将包重传。
  9. 由集线器向网络包发送数据

    • 发送数据有两种模式:半双工模式和全双工模式;
    • 在半双工模式下,为了避免冲突,先要检测是否存在其他的信号。
    • 传递过程中先由 MAC模块由数字信号转换成电信号,然后传递给 PHY/MAU。将数字信号转换成电信号的速率就是我们日常所说的网路速率。
    • MAC 模块生成的是通用的信号格式,对于不同的传输方式,PHY|MAU 将信号转化成对应的格式发送出去。
    • 对于 PHY 除了负责信号格式转换之外,还要负责监控接收的线路有没有信号进来。
    • 在半双工模式下,如果发生了信号碰撞就要进行一段时间的阻塞信号等待,时间是根据 MAC地址随机算出来的。如果阻塞信号结束之后同时发数据还是会发生碰撞,这个时候将等待时间延长一倍,十次之后返回通信错误。
    • 在全双工的模式下信号的收发可以同时进行不会发生碰撞。
  10. 接收返回包

    • 在半双工模式下,不管任何的信号只要传进来就会接收;

    • 信号到 RJ-45,接着到 PHY/MAU 将传进来的信号转换成通用格式的信号给 MAC 模块;

      • MAC 模块 从头开始将信号转换成数字信息,
      • 并且检测 FCS 以及 源、目的MAC地址 ;
      • 将数据发送到网卡的缓冲区并且发起中断信号告知一个数据包到了,准备接收。
    • 关于中断信号。

      • 网卡先向扩展总线中中断信号线发送中断信号

      • 扩展总线通知CPU

      • CPU挂起操作并处理中断程序

      • 调用驱动程序控制网卡准备接收数据

    • 那为什么来了不直接呢?

      • 操作系统不会一直监听网卡
      • 驱动程序也仅仅是一段程序
      • 通过中断打断当前的任务,就知道网卡有数据发过来了
  11. 服务器响应包从 IP 传递给 TCP

    • IP 模块收到数据之后第一步是检测数据是否是正确的;

      • 确认无误之后再查看目的IP和网卡的地址是否相同。
      • 如果不是,那么客户端直接丢弃,服务端会包转发。
    • 当发生错误的时候,将会通过 ICMP 将错误告知给发送方。

    • ICMP

      Echo reply Destination unreachable Source quench Redirect Echo Time exceeded Parameter problem
      0 3 4 5 8 11 12
    • IP 还有一个工作是关于分片的。

      • 就是之前同一个数据超过了最大值,切割成小包
      • 在这里从新按序号将小包还原成原始的包(分片重组)
      • 这里两个量:
        • 一个是ID确定是不是属于同一个分片;
        • 一个是偏移量,每个分片中小包在大包中对应的位置。

UDP 协议的说发出操作

  1. 不需要重新发的数据就用UDP,比如数据很小,一个包便能装下,那就UDP,即便重发也不过是重发一个包而已。而且返回的数据可以当作确认收到的包。
  2. 控制用的短数据可以用UDP来发送比如说DNS查询。
  3. 封装的时候是 数据+ UDP头部 + IP头部
  4. 对于UDP 遇到错误的时候是一律不管,客户端应用程序没有收到反馈会重新发送一遍数据。
  5. UDP 可发送数据的长度 = IP的长度 - IP的头部 - UDP的头部,一般长度是65507 个字节。
  6. UDP头部控制信息:发送方端口号、接收方端口号、数据长度、校验和
  7. 关于音频和视频数据。主要是为了提高实时性,所以使用UDP 进行传输。
    • 使用TCP发现数据错误进行重传会发生严重的失真,如果是UDP在丢失少量包的情况下影响并不会太大。在无需重新发送的数据上面,使用UDP是最为高效的。