网络是怎样连接的-第一第二章读书笔记

#####浏览器与服务器的交互过程

  1. 浏览器的第一步工作就是对URL进行解析(确定web服务器和要访问的文件名)
  2. 解析完后根据解析的信息生成HTTP请求(使用HTTP协议访问Web服务器)
  • HTTP 协议定义了客户端和服务器之间交互的消息内容和步骤

    • 先客户端向服务器端发送请求消息:包括URI+方法

      | 含义 | 方法 |
      | :————————————–: | :——: |
      | 获取URI 指定的信息。如果URI 指定的是文件,则返回文件的内容;get的消息体能发送的数据只有几百个字节 | GET |
      | 从客户端向服务器发送数据。一般用于发送表单中填写的数据等情况下 | POST |
      | 和GET 基本相同。不过它只返回HTTP 的消息头(message header),而并不返回数据的内容。用于获取文件最后更新时间等属性信息 | HEAD |
      | 用于通知或查询通信选项 | OPTIONS |
      | 替换URI 指定的服务器上的文件。如果URI 指定的文件不存在,则创建该文件 | PUT |
      | 删除URI 指定的服务器上的文 | DELETE |

    • 服务器端接收到请求消息后,根据请求的要求把处理的结果放在响应消息中,返回给客户端。

      | 状态码 | 含义 |
      | :–: | :————————–: |
      | 1XX | 告知请求的处理进度和情况 |
      | 2XX | 成功(200) |
      | 3XX | 表示需要进一步操作(暂时重定向302;永久重定向301) |
      | 4XX | 客户端错误(404请求失败,414url太长) |
      | 5XX | 服务器端错误 |

      1. 如果网页的内容只有文字,那么响应消息体返回给客户端就结束了(1次)
      2. 如果网页有图片,浏览器会显示文字的时候所搜图片标签,遇到后留出显示图片的空间,然后再次请求图片。因为每个请求消息中只有一个uri,所以一次只能获取1个图片。如果网页中包含3个文件,那么要请求4次。
      3. 消息体的内容作为二进制数据来处理
  1. 生成HTTP消息后,委托(委托的操作是调用Socket库中的程序组建来执行的,Socket充当一个桥梁给操作系统的协议栈)操作系统将消息发送给Web服务器(通信数据是以包的形式传送的)

    1. 在生成HTTP消息后,根据域名查询IP地址(接着浏览器将ip地址和请求消息一起交给操作系统)

    附1:TCP/IP网络的基本思路:通过小的子网网络号)(用集线器连接起来的几台计算机(主机号)),通过路由器连接起来组成大的网络。网络号+主机号的整体称为IP 地址(一个IP地址长度为32比特)。(IP地址内部用 子网掩码 来表示网络号(1)和主机号(0))

    1
    1. 发送过程:通过IP 地址我们可以判断出访问对象服务器的位置,从而将消息发送到服务器。发送者发出的消息首先经过子网中的集线器,转发到距离发送者最近的路由器上,接下来,路由器会根据消息的目的地判断下一个路由器的位置,然后将消息发送到下一个路由器,直到传送到目的地。

    附2 :根据域名查询IP 地址时,浏览器会使用Socket 库中的解析器向DNS 服务器发出查询消息,并接收服务器返回的响应消息。我们计算机上对应的DNS客户端(一段代码,在Socket库中)称为DNS解析器。

    • 调用解析器,向DNS 服务器发出查询消息
    • 服务器返回响应消息,里面包含IP地址,并储存在浏览器指定的内存地址中(接着浏览器向Web服务器发送消息时,从内存中取出IP地址,将它与HTTP请求消息一起交给操作系统)

    #####浏览器与Web服务器之间接收发消息的过程

    1. 操作系统收到IP地址和HTTP请求消息后,通过内部的协议栈向目标IP地址发送请求消息。(委托协议栈发送数字信息适合所有的网络应用程序,不局限于web)

      1
      2
      3
      4
      5
      收发数据的操作分为4个阶段,由操作系统中的协议栈来执行
      - 创建套接字(IP地址加上端口号作为TCP连接的端点叫套接字,即 IP地址:端口号)
      - 将管道连接到服务器端套接字上
      - 收发数据
      - 断开管道并删除套接字(管道连接是由客户端发起,但在断开时可以由任意一方发起)
      • 创建套接字阶段:调用Socket库的组建创建套接字,之后协议栈会返回一个描述符,来识别不同的套接字。

      • 连接阶段:委托协议栈将客户端创建的套接字与服务器那边的套接字连接起来。应用程序调用Socket库中的connect程序组建,指定描述符IP地址端口号

        1
        注:描述符是用来在一台计算机内部识别套接字的机制,那么端口号就是用来让通信的另一方能够识别出套接字的机制。
      • 通信阶段:套接字连接起来之后,调用Socket库write组建,协议栈就将数据(输入网址生产的HTTP请求消息)送入套接字,然后发送到对方的套接字中。

        1
        收到响应消息后,通过Socket库中的read组件委托协议栈来接收消息并放到接收响应的内存地址(命名为接收缓冲区)

操作系统中的网络控制软件(协议栈)和网络硬件(网卡)是如何处理数据发送请求的

协议栈内部图

(协议栈内部图 )

  • 网络应用程序:像浏览器,电子邮件客户端等,将收发数据等工作委派给下层部分。下面是Socket库,其中包含解析器,用来向DNS服务器发送查询。

  • 操作系统内部包含了协议栈:

    上半部分分为TCP+UDP:接收应用程序的委托,执行收发数据的操作

    1
    2
    浏览器、邮件等一般应用程序收发数据时用TCP;
    DNS 查询等收发较短的控制数据时用UDP。

    下半部分是IP协议:用来控制网络包收发操作

  • 网卡驱动程序:负责控制网卡硬件

  • 网卡:负责完成实际的收发操作,也就是对网线中的信号执行发送和接收的操作。

1
2
附:
套接字:协议栈内部有一块存放控制信息的内存,控制信息包括IP地址,端口号,通信操作的状态等,这些控制信息就是套接字的实体。

#####具体过程

  • 浏览器通过 Socket 库向协议栈发出委托,委托协议栈通过TCP协议来收发数据。
  1. 创建套接字:浏览器调用Socket库申请创建套接字,协议栈根据此申请执行创建套接字,在创建套接字时:

    • 首先分配一个套接字所需的内存空间,然后向其中写入初始状态。

    • 将表示这个套接字的描述符告知应用程序

      应用程序收到描述符后,向协议栈发起收发数据委托时需要提供这个描述符。

  2. 连接:浏览器调用socket库中的connect,然后协议栈将本地套接字和服务器的套接字连接。套接字创建完后,协议栈并不知道要和谁进行沟通

    1
    2
    3
    1. 浏览器可以根据网址查询ip地址及端口号,但是协议栈不知道,这是就需要调用connect将这些信息传递给协议栈。
    2. 向服务器端发送TCP包进行连接请求
    3. 分配一块内存空间用来临时存放收发信息(缓冲区)
    控制信息分类
    1. 头部中记录的控制信息:网络包开头的控制信息称为TCP头部(20个字节),还有以太网头部,IP头部。客户端和服务器端在通信过程中会将头部的信息相互确认,头部是用来记录和交换控制信息的

    2. 保存在套接字中,用来操作协议栈的操作信息:

      • 应用程序传递过来的信息,ip地址等
      • 通信对象接收到的信息
      • 收发数据操作的执行状态

    具体步骤
    • 应用程序调用connect(<描述符>,<ip地址和端口号>) ,这些信息会传递给协议栈中的TCP模块,并在TCP模块处创建 表示连接控制信息 的头部。(TCP模块会与ip对应的服务器的TCP模块交换控制信息)

      • 根据头部中的发送方和接收方端口号找到要连接的套接字
    • TCP头部创建好后,将信息传递给IP模块并委托它进行发送

      1
      IP模块执行网络包发送操作后,网络包就会通过网络传递到服务器
    • 服务器上的IP模块将接收到的数据传递给TCP模块,服务器的TCP模块根据TCP头部信息找到端口号对应的套接字,并写入相应的信息将状态改为正在连接。

    • 然后服务器的TCP模块会返回响应,将ACK控制为设为1,表示已经接收到相应的网络包。

    • 网络包返回客户端,通过IP模块到达TCP模块,并通过TCP头部信息确认是否连接成功。客户端也将ACK设置为1发回服务器,表示响应包已经收到

  3. 收发数据:应用程序调用write将发送的数据交给协议栈,协议栈收到数据后执行发送操作。

    • 通过“序号”和“ACK 号”可以确认接收方是否收到了网络包。
    1
    2
    3
    4
    5
    6
    协议栈收到数据后,会先存放在内部的发送缓冲区中,并等待下一段数据。它有两个维度,一个是长度优先,长度满MSS后发送,但是造成发送延迟;另一个是时间,经过一段时间后,就把包发送出去,但是会降低网络效率。
    - 一个网络包最大长度是MTU,1500字节
    - 去掉头部后的能容纳最大数据的长度MSS
    ------------------------
    当发送数据较大时,会分割成一个个小的网络包,当判断要发送这些数据时,在每一个数据前面加上TCP头部。
    TCP在拆分数据时,会在TCP头部写上“序号”字段(从头开始的第几个字节,实际应用过程中这个第一个号是随机的,所以在连接阶段需要将序号的初始值告诉对方) + 包的长度;对方在收到数据包后,确认返回ACK号(一共收了多少字节)

    • 通过滑动窗口管理ACK号:在发送完一个包后,不等待这个包的ACK返回,直接发送后续一系列包,并且客户端告知发送方自己能接收的最大数据量(称为窗口大小),发送方根据这个来控制数据发送操作。

      1
      2
      3
      1. 接收方在接到包后,先将数据保存在接收缓冲区中,计算ACK号并组装数据包,将数据传递给应用程序,然后释放缓冲区
      2. 当接收方将缓冲区的数据传递给应用程序释放缓冲区的时候,需要将窗口大小字段发送给发送方
      3. 连续的ACK号可以合并,发送最后一个ACK号即可,并会和窗口大小字段合并在一个包里一起发送
  4. 断开连接:双方都可以发起断开连接,然后过一段时间后客户端删除套接字。

    1
    2
    3
    4
    5
    以服务器发起断开为例:
    1. 调用Socket库中的close,协议栈生产断开信息的TCP头部,将FIN设为1,并委托IP模块发送数据
    2. 客户端收到网络包后,将自己的套接字标记为断开操作状态。并反馈ACK号给服务器
    3. 客户端也会调用close,生成FIN为1的TCP包,发送服务器
    4. 服务器返回ACK号

#####收发数据总结:

  1. 第一步是创建套接字,服务器端启动时就创建好套接字并等待连接状态,客户端一般是发送请求的时候创建套接字

    包含了通信的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。

  2. 然后客户端向服务器端发起连接操作。客户端生成一个SYN为1的TCP包,头部也包含发送数据的初始序号(随机生成)和窗口大小(接收缓冲区最多能接收的容量大小)。服务器端返回SYN为1的TCP包,也包含了序号和窗口大小,还有表示确认收到包的ACK号(为1),然后客户端再返回一个确认的ACK号。3次握手确认。连接完毕。

    1
    SYN 是 Synchronize(同步)的缩写,意思是通过告知初始序号使通信双方保持步调一致,以便 完成后续的数据收发检查
  3. 数据收发阶段,客服端向服务器端发送请求信息,TCP将请求信息切分成一个个数据包,并打上TCP头部(头部包含序号,它表示当前发送的是第几个字节的数据),然后发送给服务器。服务器返回ACK号。起初服务器不断接收数据存储在缓冲区中,随着数据传递给应用程序,缓冲区空间被释放,此时将窗口大小反馈告知客户端。当收到请求后,服务器端向客户端返回相应消息。这个过程和刚才相反。

  4. 服务器响应消息发送完后,开始执行断开操作。以HTTP1为例,客户端发起断开过程。客户端发送一个FIN为1的TCP包,客户端返回一个确认收到的ACK号,然后双方交换一组方向相反的过程。最后,在一段时间后,套接字会被删除。

IP模块

TCP模块在执行连接,收发和断开操作时,都需要委托IP模块将数据封装成包发送给通信对象(整个传输是由集线器和路由器等设备完成的,IP模块是传输过程的一个入口)。网络包是由头部信息+数据组成的。

TCP/IP包包含如下两个头部,MAC头部(包含MAC地址) + IP头部(包含IP地址)

网络中有路由器和集线器两种不同的转发设备,他们在传输网络包时有着各自的分工

  • 路由器根据目标地址判断下一个路由器的位置(按照IP规则传输)

    IP协议根据目标地址判断下一个IP转发设备的位置

  • 集线器在子网中将网络包传输到下一个路由(按照以太网规则)

    子网中的以太网协议将包传输到下一个转发设备

整个传输过程:

首先发送方将服务器IP地址写入IP头部(IP协议就可以根据地址查找包的传输方向),IP协议会查找下一个路由器的以太网地址,并写在MAC头部,这样以太网协议就知道要将这个包发送到哪个路由器上。IP协议协议会委托以太网协议把包传输出去)

MAC头部 - IP头部 - TCP头部+数据 , 经过集线器(有以太网协议表,根据MAC头部信息查出下一个路由器地址并发送到下一个路由器),路由器(有IP协议表(即路由表),根据IP头部的信息查出下一个路由器地址和MAC头部地址(通过ARP查询对应的MAC地址),并改写MAC头部)