Network

一、以浏览器的一次请求开始

概述:主要是讲解浏览器 解析网址、生成HTTP请求消息、委托协议栈发送消息等步骤。

当浏览器输入一个地址,会有如下几步:

  1. 解析地址,生成请求消息
    1. 如何解析?
    2. 请求消息长什么样?
  2. 向DNS服务器查询Web服务器的IP
    1. 获得IP地址是浏览器的职责
    2. 委托操作系统发出请求前,需要提供对方IP
    3. DNS服务器如何得到域名对应IP?
  3. 委托协议栈发出请求

解析地址

URL & URI

URL(Uniform Resource Locator)URI(Uniform Resource Identifier)都是用于标识互联网上资源的标准方法;

URI是一个用于标识某一互联网资源的字符串,URL是URI的子集,提供找到该资源的路径。

URL元素: http: // Web服务器名称 / 目录名 / …… / 文件名

其中目录名、文件名都可以省略,

当文件名被省略时,如https://www.baidu.com/,可以理解为后面的文件名被省略了,服务器会设置一个默认文件名(如index.html)

请求消息

请求行: <方法> <空格> <空格> <HTTP版本>

消息头(可以多行):<字段名>:<字段值>

<空行>

<消息体>

如果响应里包含图片标签(其他的也一样),会进一步解析,发起更多的请求,并渲染在页面上。

响应消息

这里提一下响应消息

状态行:<HTTP版本><空格><状态码><空格><响应短语>

消息头:<字段名>:<字段值>

<空行>

<消息体>

状态码

  • 100 告知请求处理进度和情况,没怎么见过
  • 200 成功
  • 3xx 需要进一步操作
  • 4xx 客户端错误
  • 5xx 服务器错误

DNS查询IP

先了解一下TCP/IP的基本思路。

一些小的子网,通过路由器连接起来,组成一个大的网络。

这里子网可以理解为用集线器连接起来的几台计算机,将它看作一个单位,称为子网。

网络中,所有设备都会被分配一个地址,相当于“xx号xx室”,其中号被分配给整个子网,室分配给子网中的计算机。

这里“号”称为网络号,“室”称为“主机号”,这个地址整体称为IP地址。

通过IP地址我们可以判断出对象服务器的位置,从而发送消息到正确的位置。

消息传送的具体过程概述:

发送者发出的消息先经过子网中的集线器,转发到距离最近的路由器上,
路由器会根据消息的目的地判断下一个路由器的位置,发送到下一个路由器,

不断重复这个过程,把消息送达目的地

IP地址

实际IP地址是一串32比特的数字,按照8比特为一组分为4组。

仅凭一串数字无法区分哪部分是网络号,哪部分是主机号,我们还需要一个子网掩码。

格式上是一串32比特的数字,左边全部是1,右边全部是0,其中为1的部分表示主机号

可以简写成数字,表示左边有多少个1

主机号部分全部为0,表示整个子网而不是某个设备

主机号部分全部为1,表示向子网所有设备发送包,即广播

使用Socket库查询IP地址

socket库提供了查询DNS的函数,可以直接调用,可以认为是 ip = gethostbyname("www.baidu.com")

库的具体实现也是需要委托操作系统协议栈来发出网络请求

DNS服务器

DNS维护了一个域名和IP的对照表(实际上DNS会更复杂一些,有一个类型的概念,但我们可以简单认为都是Web服务器在查)

接收到请求后,从表里查找相应的记录并返回。

但是世界上的服务器信息,不可能放在一台DNS服务器中(真放不下

这个时候看DNS服务器是如何处理的?

简单来说,是把信息放在不同的服务器中,通过接力配合查找出对应的信息。

要理解这个机制具体怎么运行,要先了解域名的层次结构:

DNS的域名通过句点来分割,每个层级都被称为域,越靠右的位置表示层级越高,这种具有层次结构的域名信息会注册到DNS服务器中。

一台DNS服务器会管理一个或多个域,由此DNS服务器也具有和域名一样的层次结构,每个域的信息都存放在相应层级的DNS服务器中。

管理一个域的DNS服务器会把自己的信息注册到管理上一级域的DNS服务器中

最上层的DNS服务器称为根域,所有DNS服务器都会记录根域的信息

img

具体如何运行呢:

  1. 客户端访问某一台DNS服务器
  2. 这台DNS服务器会请求到根域服务器
  3. 这台DNS服务器从根域服务器一路找到下层的某台目标DNS服务器,获得IP地址
  4. 这台DNS服务器把对应的IP地址返回给客户端

DNS服务器有缓存功能,可以记住之前查询过的域名,加速查找(冷热数据的一种应用)

委托协议栈发出请求

创建套接字并连接,就是著名的三次握手。

  1. 客户端创建套接字
  2. 将自己的套接字与服务端的套接字连接起来,形成管道
    1. 需要指定刚创建的套接字、服务器IP地址、端口号
  3. 收发数据
  4. 发送完成后,断开管道并删除套接字
    1. 一开始是服务端来断开,服务端判断这次请求内容发完了就断开
    2. 后面发现一次连接只传输一次内容 太低效了。于是设计出一次连接收发多个请求和响应的方法,当所有数据都请求完成后,客户端会主动断开连接

补充一点服务器这边套接字的内容

服务器包含两类套接字:

  1. 监听套接字
    • 服务端首先创建一个监听套接字,这个套接字绑定到特定的IP地址和端口上。
    • 这个套接字用来监听来自客户端的连接请求。
  2. 连接套接字
    • 当服务端的监听套接字接受(accept)一个来自客户端的连接请求时,它会为这个特定的连接创建一个新的套接字,我们称之为“连接套接字”。
    • 这个连接套接字是唯一的,专门用于服务器和该特定客户端之间的通信。
    • 每个连接套接字都有一个独特的套接字对(Socket Pair),包括:客户端的IP地址和端口号,服务器的IP地址和端口号。

所以不同客户端实际上连接的不是同一个套接字。

即使不同客户端连接到服务端的同一个IP地址和端口,服务端也能通过不同的连接套接字来区分和管理不同的客户端连接。

二、TCP/IP & 协议栈

概述:讲解协议栈如何处理数据发送请求

创建套接字

协议栈内部结构

协议栈

协议栈包含TCP、UDP、IP

TCP和UDP 接受应用程序的委托执行收发数据的操作

IP 负责把网络包发送给通信对象

套接字是什么

套接字记录了用于控制通信操作的各种控制信息。例如 客户端的IP、端口 服务端的IP、端口

协议栈根据这些信息判断下一步的行动。

win中可以用 netstat 命令显示套接字的内容

连接服务器

通信双方交换控制信息,在套接字中记录这些信息。

还要分配一块用于临时存放收发数据的内存空间,称为缓冲区。

补充一些关于控制信息的。

有一些控制信息不仅连接时需要,数据收发和断开连接都需要。

所以这些信息会被添加在客户端和服务器之间传递的网络包的开头。连接阶段没有实际数据,只有控制信息。

这种控制信息被称为头部。

以太网、IP协议都有自己的控制信息,也叫头部。为了区分,我们会分别记作TCP头部、以太网头部、IP头部

客户端和服务器在通信中会将必要信息记录在头部并互相确认。

理解了头部各个字段的含义,才能理解通信的过程。

具体的操作

  1. 在TCP模块创建表示连接控制信息的头部 【SYN=1】
  2. TCP头部创建好以后,把信息传递给IP模块并委托它发送
  3. 请求通过网络到达服务器,IP模块把接受到的请求传递给TCP模块。TCP模块找到对应的套接字并写入相应信息(这块可以看上面,实际是新建一个套接字用来负责客户端的请求)
  4. 服务器返回响应【SYN=1 ACK=1】
  5. 请求通过网络到达客户端,套接字中写入服务器的IP地址、端口号信息。返回一次响应【ACK = 1】

其实就是双方各自确认对方可以收到自己的信息。

就是

A:歪歪歪,能听到不

B:能听到 你呢

A:可以

收发数据

应用程序调用write将要发送的数据交给协议栈
  • 协议栈不关心应用程序传来的数据是什么内容。对于协议栈都是一定长度的二进制字节序列
  • 协议栈不会一收到数据就发送出去,而是会存放在内部的发送缓冲区,等待后面的数据一起传送
    • 因为一次将多少数据交给协议栈是应用程序自行决定的。有些应用程序会小段传送数据,这种情况下如果一收到数据就发送,在网络中会出现大量小包,导致网络效率下降。
    • 因此会积累一定数量的数据才会发送,这个判断标准不同的操作系统会有不同,但是都是由以下要素来判断的
      • MTU:每个网络包的长度(包含头部),去除头部叫MSS,收到数据长度接近MSS时发送出去,就可以避免大量小包的问题
      • 时间:避免为了等待导致发送延迟
交给协议栈后

较大的数据会进行拆分。TCP会拆分数据,给每块数据前面加上TCP头部,交给IP模块来执行发送数据的操作


Network
https://yzaf.top/2024/csbasic/Network/
作者
why
发布于
2024年1月23日
许可协议