计算机网络笔记

计算机网络

1、网络模型

OSI七层网络模型:应用层、表示层、会话层、传输层、网络层、数据链路层、物理层

osi七层模型

TCP/IP四层模型:应用层、传输层、网络层、网络接口层

应用层是工作在操作系统中的用户态,传输层及以下则工作在内核态

TCP-IP-4-model
  • 应用层:主要提供两个终端设备上的应用程序之间信息交换的服务,它定义了信息交换的格式,消息会交给传输层来传输。

    • 应用层定义很多网络通信协议:
      • 超文本传输协议 HTTP
      • 文件传输协议 FTP
      • 简单邮件传输协议 SMTP
      • 提供远程登录的安全外壳协议 SSH
      • ...
  • 传输层:主要任务是负责向两台终端设备进程之间的通信提供通用的数据传输服务。

    • 传输层两种协议
      • 用户数据协议(UDP,User Datagram Protocol)
        • 面向无连接,实时性相对更好,传输效率也高
        • 不可靠。当然,UDP 也可以实现可靠传输,把 TCP 的特性在应用层上实现就可以
      • 传输控制协议(TCP,Transmisson Control Protocol)
    • 当设备作为接收方时,传输层则要负责把数据包传给应用,但是一台设备上可能会有很多应用在接收或者传输数据,因此需要用一个编号将应用区分开来,这个编号就是端口
      • 80:web服务器
      • 21:FTP文件传输
      • 22:SSH安全登录
      • 23:Telnet远程登录
      • 80:http
      • 443:https
      • 3306:mysql
      • 6379:redis
      • 9200:elasticsearch
  • 网络层:负责为分组交换网上的不同主机提供通信服务

    • 网络层使用IP协议:IP 协议会将传输层的报文作为数据部分,再加上 IP 包头组装成 IP 报文

      img

      网络层负责将数据从一个设备传输到另一个设备,ip地址对设备编号进行区分设备。

      IP 地址分成两种意义:

      • 网络号,负责标识该 IP 地址是属于哪个「子网」的;

        将 10.100.122.2 和 255.255.255.0 进行按位与运算,就可以得到网络号

      • 主机号,负责标识同一「子网」下的不同主机;

        将 10.100.122.2 和 255.255.255.0 取反后进行按位与运算,就可以得到主机号

  • 网络接口层:

    • 数据链路层:将网络层交下来的 IP 数据包前面加上MAC头部组装成帧,在两个相邻节点间的链路上传送帧。
    • 物理层:实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异。
img

每一层的封装格式:

img

2、HTTP

超文本:通过超链接的方式,将网络上包括文本图片等在内的各种各样的消息组织在一起的网状文本。

HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。

2.1、响应状态码

HTTP/1.0仅定义了16种状态码,HTTP/1.1中新加入了大量的状态码。

100:在请求大资源前的预热请求 http1.1新增

200:请求响应成功,200

3xx:请求重定向

  • 301:表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问;

  • 302:表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问;

  • 304:表示资源未修改,重定向已存在的缓冲文件

4xx:客户端错误状态码,服务器无法处理请求

  • 403:表示服务器禁止访问资源,并不是客户端的请求出错。

  • 404:表示请求的资源在服务器上不存在或未找到

5xx:服务器错误状态码,服务器请求处理出错

  • 500 :笼统通用的错误码
  • 502:表示服务器自身工作正常,访问后端服务器发生了错误

 五大类 HTTP 状态码

2.2、HTTP常见字段

  • Host字段:指定服务器域名

  • Content-Length字段:表明服务器本次返回数据的长度

  • Connection字段:客户端要求服务器长连接

    Connection: keep-alive
    
  • Content-Type:服务器告诉客户端响应数据的格式

    Content-Type: text/html; charset=utf-8
    

    客户端请求时,可以使用 Accept 字段指明自己可以接收的数据类型

    Accept: */*
    
  • Content-Encoding:表示服务器返回的数据使用了什么压缩格式

    Content-Encoding: gzip
    

    客户端在请求时,用 Accept-Encoding 字段说明自己可以接受哪些压缩方法

    Accept-Encoding: gzip, deflate
    

2.3、Get 和 Post

Get语义是从服务器获取指定资源

  • 请求参数一般写在URL中,URL 规定只能支持 ASCII,浏览器对URL的长度有限制
  • 安全且幂等,但也不绝对,当使用Get进行新增和提交数据时,也是不安全,和不幂等的
  • 请求的数据可以做缓存

Post的语义时根据请求负荷(报文body)对指定的资源做出处理

  • 携带的数据写在报文的body中,支持任意格式,任意大小
  • 会修改服务器上的资源,不安全,不是幂等
  • 不能作为缓存

因为 HTTP 传输的内容都是明文的,虽然在浏览器地址拦看不到 POST 提交的 body 数据,但是只要抓个包就都能看到了。

所以,要避免传输过程中数据被窃取,就要使用 HTTPS 协议,这样所有 HTTP 的数据都会被加密传输。

2.4、缓存处理

强制缓存:只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存

强缓存是利用下面这两个 HTTP 响应头部(Response Header)字段实现的,它们都用来表示资源在客户端缓存的有效期:

  • Cache-Control, 是一个相对时间;优先级高于Expires
  • Expires,是一个绝对时间;

具体的实现流程如下:

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 Cache-Control,Cache-Control 中设置了过期时间大小;
  • 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与 Cache-Control 中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
  • 服务器再次收到请求后,会再次更新 Response 头部的 Cache-Control。

协商缓存:通过服务端告知客户端是否可以使用缓存的方式

某些请求的响应码是 304,这个是告诉浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存。

协商缓存可以基于两种头部来实现:

  • 请求头部中的 If-Modified-Since 字段与响应头部中的 Last-Modified 字段实现
    • 响应头部中的 Last-Modified:标示这个响应资源的最后修改时间;
    • 请求头部中的 If-Modified-Since:与 Last-Modified 进行对比,若 Last-Modified > If-Modified-Since ,则说明资源被修改过,服务器返回最新资源;反之,服务器响应 304,走缓存。
  • 请求头部中的 If-None-Match 字段与响应头部中的 ETag 字段
    • 响应头部中 Etag:唯一标识响应资源;
    • 请求头部中的 If-None-Match:再次请求时,将请求头中的 If-None-Match 的值设置为 Etag ,服务器收到请求后,进行对比,如果资源没有变化返回 304,走缓存;否则返回 200,并响应资源。

如果 HTTP 响应头部同时有 EtagLast-Modified 字段的时候, Etag 的优先级更高,也就是先会判断 Etag 是否变化了,如果 Etag 没有变化,然后再看 Last-Modified

注意,协商缓存这两个字段都需要配合强制缓存中 Cache-control 字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求

使用 ETag 字段实现的协商缓存的过程如下;

  • 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在 Response 头部加上 ETag 唯一标识,这个唯一标识的值是根据当前请求的资源生成的;
  • 当浏览器再次请求访问服务器中的该资源时,首先会先检查强制缓存是否过期,如果没有过期,则直接使用本地缓存;如果缓存过期了,会在 Request 头部加上 If-None-Match 字段,该字段的值就是 ETag 唯一标识;
  • 服务器再次收到请求后,会根据请求中的 If-None-Match 值与当前请求的资源生成的唯一标识进行比较
    • 如果值相等,则返回 304 Not Modified,不会返回资源
    • 如果不相等,则返回 200 状态码和返回资源,并在 Response 头部加上新的 ETag 唯一标识;
  • 如果浏览器收到 304 的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。

2.5、HTTP/1.1 特性

长连接

HTTP/1.0 默认使用短连接

  • 客户端和服务器每进行一次 HTTP 操作,就建立一次连接,任务结束就中断连接。
  • 每遇到这样一个 Web 资源,浏览器就会重新建立一个TCP连接,这样就会导致有大量的“握手报文”和“挥手报文”占用了带宽。

HTTP/1.1 优化为默认长连接模式

  • 当一个网页打开完成后,客户端和服务器之间用于传输 HTTP 数据的 TCP 连接不会关闭,客户端再次访问这个服务器时,会继续使用这一条已经建立的连接。

HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接。

实现长连接需要客户端和服务端都支持长连接。

管道网络传输

客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。

队头阻塞

管道传输解决了请求的队头阻塞,但未解决响应的队头阻塞。

因为当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一同被阻塞了,会招致客户端一直请求不到数据。

Host头处理

HTTP/1.1在请求头中加入了Host字段。

http 1.0 请求头

GET /home.html HTTP/1.0

http1.1 请求头

GET /home.html HTTP/1.1
Host: example1.org

带宽优化

HTTP1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接。

2.6、HTTP vs HTTPS

HTTP:

以TCP(传输层)作为底层协议

端口:80

优点:扩展性强、速度快、跨平台支持性好。

HTTPS:

HTTPS 是基于 HTTP 的,也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证。

端口:443

优点:保密性好、信任度高。

SSL/TLS 协议

非对称加密:

采用两个密钥:公钥和私钥

任何一个发送者都可以拥有公钥进行信息加密,只有接收方可以拥有私钥解密。

对称加密:

通信双方共享唯一密钥 k,加解密算法已知,加密方利用密钥 k 加密,解密方利用密钥 k 解密,保密性依赖于密钥 k 的保密性。

SSL/TLS 实际对消息的加密使用的是对称加密。但是唯一密钥k使用非对称加密,保证密钥的绝对安全。

HTTPS 如何解决不安全现象

HTTP不安全现象:

  • 明文传输:账号信息泄露
  • 不验证通信方身份:访问盗版淘宝网站
  • 无法验证报文完整性:植入广告

HTTPS对应解决方案:

  • 混合加密:HTTPS 采用的是对称加密非对称加密结合的「混合加密」方式

    image.png
  • 摘要算法+数字签名:实现数据完整性:为了解决伪造哈希值,使用摘要算法+数字签名的方式传输数据

    • 摘要算法(哈希函数)来计算出内容的哈希值,也就是内容的「指纹」。然而通过哈希算法可以确保内容不会被篡改,但是并不能保证「内容 + 哈希值」不会被中间人替换,因为这里缺少对客户端收到的消息是否来源于服务端的证明。
    • 那为了避免这种情况,计算机里会用非对称加密算法来解决:私钥加密,公钥解密。这个目的是为了保证消息不会被冒充,因为私钥是不可泄露的,如果公钥能正常解密出私钥加密的内容,就能证明这个消息是来源于持有私钥身份的人发送的。我们常说的数字签名算法,就是用的是这种方式,不过私钥加密内容不是内容本身,而是对内容的哈希值加密
  • 数字证书:存放服务器公钥

    前面我们知道:

    • 可以通过哈希算法来保证消息的完整性;
    • 可以通过数字签名来保证消息的来源可靠性(能确认消息是由持有私钥的一方发送的);

    但是这还远远不够,还缺少身份验证的环节,万一公钥是被伪造的呢?

    在计算机里,数字证书认证机构 CA 将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。

    数子证书工作流程

2.7、HTTP/1.1、HTTP/2、HTTP/3 演变

HTTP/1.1 瓶颈:

  • 请求 / 响应头部(Header)未经压缩就发送,首部信息越多延迟越大。
  • 队头阻塞
  • 没有请求优先级控制;
  • 请求只能从客户端开始,服务器只能被动响应。

HTTP/2 优化:

  • HTTP/2 协议是基于 HTTPS 的,安全
  • 头部压缩
  • 报文采用二进制格式,增加数据传输速率
  • 多路复用,不需要排队,解决队头阻塞问题
  • 服务器推送,可以主动向客户端发送消息

问题:一旦发生了丢包现象,就会触发 TCP 的重传机制,这样在一个 TCP 连接中的所有的 HTTP 请求都必须等待这个丢了的包被重传回来TCP层面出现队头阻塞。

HTTP/3 优化:

HTTP/3 把TCP改成UDP,但是基于QUIC协议,依然能够保持类似TCP的可靠性传输。

  • 无队头阻塞
  • 更快的连接建立
  • 连接迁移

2.8、HTTP/1.1 如何优化

我们可以从下面这三种优化思路来优化 HTTP/1.1 协议:

  • 尽量避免发送 HTTP 请求
  • 在需要发送 HTTP 请求时,考虑如何减少请求次数
  • 减少服务器的 HTTP 响应的数据大小

img

2.9、HTTPS RSA四次握手

以最简单的 RSA 密钥交换算法,来看看它的 TLS 握手过程。

TLS 第一次握手

客户端首先会发一个「Client Hello」消息,字面意思我们也能理解到,这是跟服务器「打招呼」。

img

消息里面有客户端使用的 TLS 版本号、支持的密码套件列表,以及生成的随机数(Client Random,这个随机数会被服务端保留,它是生成对称加密密钥的材料之一。

TLS 第二次握手

当服务端收到客户端的「Client Hello」消息后,会确认 TLS 版本号是否支持,和从密码套件列表中选择一个密码套件,以及生成随机数(Server Random

接着,返回「Server Hello」消息,消息里面有服务器确认的 TLS 版本号,也给出了随机数(Server Random),然后从客户端的密码套件列表选择了一个合适的密码套件。

img

然后,服务端为了证明自己的身份,会发送「Server Certificate」给客户端,这个消息里含有数字证书。

img

随后,服务端发了「Server Hello Done」消息,目的是告诉客户端,我已经把该给你的东西都给你了,本次打招呼完毕。

img

客户端验证证书

一个数字证书通常包含了:

  • 公钥;
  • 持有者信息;
  • 证书认证机构(CA)的信息;
  • CA 对这份文件的数字签名及使用的算法;
  • 证书有效期;
  • 还有一些其他额外信息;

下图所示,为数字证书签发和验证流程:

img

CA 签发证书的过程,如上图左边部分:

  • 首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;
  • 然后 CA 会使用自己的私钥将该 Hash 值加密,生成 Certificate Signature,也就是 CA 对证书做了签名;
  • 最后将 Certificate Signature 添加在文件证书上,形成数字证书;

客户端校验服务端的数字证书的过程,如上图右边部分:

  • 首先客户端会使用同样的 Hash 算法获取该证书的 Hash 值 H1;
  • 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密 Certificate Signature 内容,得到一个 Hash 值 H2 ;
  • 最后比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。

TLS 第三次握手

客户端验证完证书后,认为可信则继续往下走。接着,客户端就会生成一个新的随机数 (pre-master),用服务器的 RSA 公钥加密该随机数,通过「Change Cipher Key Exchange」消息传给服务端。

img

服务端收到后,用 RSA 私钥解密,得到客户端发来的随机数 (pre-master)。

至此,客户端和服务端双方都共享了三个随机数,分别是 Client Random、Server Random、pre-master

于是,双方根据已经得到的三个随机数,生成会话密钥(Master Secret),它是对称密钥,用于对后续的 HTTP 请求/响应的数据加解密。

生成完会话密钥后,然后客户端发一个「Change Cipher Spec」,告诉服务端开始使用加密方式发送消息。

img

然后,客户端再发一个「Encrypted Handshake Message(Finishd)」消息,把之前所有发送的数据做个摘要,再用会话密钥(master secret)加密一下,让服务器做个验证,验证加密通信是否可用和之前握手信息是否有被中途篡改过。

img

可以发现,「Change Cipher Spec」之前传输的 TLS 握手数据都是明文,之后都是对称密钥加密的密文。

TLS 第四次握手

服务器也是同样的操作,发「Change Cipher Spec」和「Encrypted Handshake Message」消息,如果双方都验证加密和解密没问题,那么握手正式完成。

3、TCP

什么是TCP

TCP 是面向连接的、可靠的、基于字节流的传输层通信协议。

  • 面向连接:一对一连接,不能向UDP那样一对多
  • 可靠:无论网络链路怎么变化,TCP都能保证一个报文一定能到达接收端
  • 基于字节流

TCP头部格式:

TCP 头格式
  • 序列号:在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该「数据字节数」的大小。用来解决网络包乱序问题。
  • 确认应答号:指下一次「期望」收到的数据的序列号,发送端收到这个确认应答以后可以认为在这个序号以前的数据都已经被正常接收。用来解决丢包的问题。
  • 控制位:
    • ACK:该位为1时,确认应答。
    • RST:该位为 1 时,表示 TCP 连接中出现异常必须强制断开连接。
    • SYN:该位为 1 时,表示希望建立连接。
    • FIN:该位为 1 时,表示今后不会再有数据发送,希望断开连接。

TCP 和 UDP 有什么区别

UDP 头部格式:

UDP 头部格式
  • 目标和源端口:主要是告诉 UDP 协议应该把报文发给哪个进程。
  • 包长度:该字段保存了 UDP 首部的长度跟数据的长度之和。
  • 校验和:校验和是为了提供可靠的 UDP 首部和数据而设计,防止收到在网络传输中受损的 UDP包。

TCP 和 UDP 区别:

  1. 连接:
    • TCP:面向连接,传输数据前先要建立连接。
    • UDP:无连接,即刻传输
  2. 服务对象
    • TCP:一对一
    • UDP:可以一对多
  3. 可靠性
    • TCP:保证数据无差错、不丢失、不重复、按需到达
    • UDP:不保证可靠性
  4. 拥塞控制、流量控制
    • TCP:拥有拥塞控制、流量控制
    • UDP:没有
  5. 首部开销
    • TCP:首部长度较长,开销大
    • UDP:首部固定只有8字节,开销较少
  6. 传输方式
    • TCP:流式传输,没有边界,但保证顺序和可靠
    • UDP:一个包一个包发送,没有边界,但可能丢包和乱序
  7. 分片不同
    • TCP:如果数据长度大于MSS,则分片进行传输
    • UDP:如果数据长度大于MTU,则在 IP 层进行分片

TCP 和 UDP 应用场景:

TCP:

  • ftp文件传输
  • HTTP/HTTPS

UDP:

  • 包总量较少的通信,如DNS,SNMP
  • 视频、音频等多媒体通信
  • 广播通信

3.1、三次握手和四次挥手

3.1.1、三次握手

TCP是面向连接的,因此在通信前需要先建立连接。

TCP 三次握手
  • 一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态
第一个报文—— SYN 报文
  • 客户端会随机初始化序号(client_isn),将此序号置于 TCP 首部的「序号」字段中,同时把 SYN 标志位置为 1 ,表示 SYN 报文。接着把第一个 SYN 报文发送给服务端,表示向服务端发起连接,该报文不包含应用层数据,之后客户端处于 SYN-SENT 状态。
第二个报文 —— SYN + ACK 报文
  • 服务端收到客户端的 SYN 报文后,首先服务端也随机初始化自己的序号(server_isn),将此序号填入 TCP 首部的「序号」字段中,其次把 TCP 首部的「确认应答号」字段填入 client_isn + 1, 接着把 SYNACK 标志位置为 1。最后把该报文发给客户端,该报文也不包含应用层数据,之后服务端处于 SYN-RCVD 状态。
第三个报文 —— ACK 报文
  • 客户端收到服务端报文后,还要向服务端回应最后一个应答报文,首先该应答报文 TCP 首部 ACK 标志位置为 1 ,其次「确认应答号」字段填入 server_isn + 1 ,最后把报文发送给服务端,这次报文可以携带客户到服务器的数据,之后客户端处于 ESTABLISHED 状态。
  • 服务器收到客户端的应答报文后,也进入 ESTABLISHED 状态。

从上面的过程可以发现第三次握手是可以携带数据的,前两次握手是不可以携带数据的,这也是面试常问的题。

一旦完成三次握手,双方都处于 ESTABLISHED 状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。

为什么要进行三次握手?

三次握手才能保证双方具有接收和发送的能力。

  1. 避免历史连接:在两次握手的情况下,被动发起方没有中间状态给主动发起方来阻止历史连接,导致被动发起方可能建立一个历史连接,造成资源浪费。

    例如:当网络阻塞时,主动发起方重新发起一个连接,但是被动发起方首先接收到上一次连接请求,由于只有两次握手,被动发起方此时处于 ESTABLISHED 状态,并可以向主动发起方传输数据。主动发起方接收响应,判断此时响应是历史连接,发送 RST 断开连接。因此,被动发起方建立的历史连接和发送的数据浪费了。

    三次握手:(如何避免历史连接?)

    • 一个「旧 SYN 报文」比「最新的 SYN 」 报文早到达了服务端;

    • 那么此时服务端就会回一个 SYN + ACK 报文给客户端;

    • 客户端收到后可以根据自身的上下文,判断这是一个历史连接(序列号过期或超时),那么客户端就会发送 RST 报文给服务端,表示中止这一次连接。

      三次握手避免历史连接

    两次握手:「被动发起方」在收到 SYN 报文后,就进入 ESTABLISHED 状态,意味着这时可以给对方发送数据给,但是「主动发」起方此时还没有进入 ESTABLISHED 状态,而「被动发起方」在第一次握手的时候就进入 ESTABLISHED 状态,所以它可以发送数据的,但是它并不知道这个是历史连接,它只有在收到 RST 报文后,才会断开连接。

    两次握手无法阻止历史连接

    因此,三次握手能够在「被动发起方」发送数据前,也就是建立连接之前,要阻止掉历史连接,这样就不会造成资源浪费。

  2. 同步双方初始序列号:客户端发送 SYN 报文初始化序列号,服务端回应 ACK 表示成功接收,并初始化序列号,客户端同样需要回应 ACK 表示成功接收,这样才能保证双方初始化序列号被可靠同步,这样一来一回,才能保证双方的初始序列号都能被可靠同步。

    四次握手与三次握手

    四次握手其实也能够可靠的同步双方的初始化序号,但由于第二步和第三步可以优化成一步,所以就成了「三次握手」。

  3. 避免资源浪费:客户端没有收到 ACK 响应时,就会重新发送 SYN 。当网络拥塞时,由于只有两次握手,每次客户端发送一个 SYN 报文时,服务端都会建立一个连接。如果客户端的 SYN 阻塞了,重复发送多次 SYN 报文,那么服务器在收到请求后就会建立多个冗余的无效链接,造成不必要的资源浪费。

    两次握手会造成资源浪费

为什么每次建立 TCP 连接时,初始化的序列号都要求不一样呢?

  • 防止历史报文被下一个相同四元组的连接接收
  • 防止黑客伪造的相同序列号TCP报文被对方接收
3.1.2、四次挥手

双方都可以主动断开连接,断开连接后主机中的「资源」将被释放,四次挥手的过程如下图:

客户端主动关闭连接 —— TCP 四次挥手
  • 客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。
  • 服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSED_WAIT 状态。
  • 客户端收到服务端的 ACK 应答报文后,之后进入 FIN_WAIT_2 状态。
  • 等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。
  • 客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态
  • 服务器收到了 ACK 应答报文后,就进入了 CLOSED 状态,至此服务端已经完成连接的关闭。
  • 客户端在经过 2MSL 一段时间后,自动进入 CLOSED 状态,至此客户端也完成连接的关闭。

你可以看到,每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手

这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

为什么断开连接需要四次挥手?

  • 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
  • 服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。

从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACKFIN 一般都会分开发送,从而比三次握手导致多了一次。

为什么需要 TIME_WAIT 状态?

主动发起关闭连接的一方,才会有 TIME-WAIT 状态。

需要 TIME-WAIT 状态,主要是两个原因:

  • 防止历史连接中的数据,被后面相同四元组的连接错误的接收;

    为了防止历史连接中的数据,被后面相同四元组的连接错误的接收,因此 TCP 设计了 TIME_WAIT 状态,状态会持续 2MSL 时长,这个时间足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。

  • 保证「被动关闭连接」的一方,能被正确的关闭;

    TIME-WAIT 作用是等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。例如,第四次握手丢失,服务器会重传 FIN 并等待客户端 ACK

3.2、TCP 重传、滑动窗口、流量控制、拥塞控制

3.2.1、重传机制

超时重传

重传机制的其中一个方式,就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的 ACK 确认应答报文,就会重发该数据,也就是我们常说的超时重传

TCP 会在以下两种情况发生超时重传:

  • 数据包丢失
  • 确认应答丢失

超时重传时间 RTO 的值应该略大于报文往返 RTT 的值

快速重传

不以时间为驱动,而是以数据驱动重传

快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段。

快速重传机制只解决了一个问题,就是超时时间的问题,但是它依然面临着另外一个问题。就是重传的时候,是重传之前的一个,还是重传所有的问题。

SACK( Selective Acknowledgment 选择性确认)

这种方式需要在 TCP 头部「选项」字段里加一个 SACK 的东西,它可以将缓存的数据发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据

如果要支持 SACK,必须双方都要支持。

Duplicate SACK

Duplicate SACK 又称 D-SACK,其主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。

3.2.2、滑动窗口

解决发送端每发送一个数据包,需要等待服务端应答才能发送下一个数据包,造成通信效率低的问题。

那么可以通过指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值

窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。

通常窗口的大小是由接收方的窗口大小来决定的。

发送方的滑动窗口

下图就是发送方缓存的数据

img

当发送方把数据「全部」都一下发送出去后,可用窗口的大小就为 0 了,表明可用窗口耗尽,在没收到 ACK 确认之前是无法继续发送数据了,如下图

可用窗口耗尽

在下图,当收到之前发送的数据 32~36 字节的 ACK 确认应答后,如果发送窗口的大小没有变化,则滑动窗口往右边移动 5 个字节,因为有 5 个字节的数据被应答确认,接下来 52~56 字节又变成了可用窗口,那么后续也就可以发送 52~56 这 5 个字节的数据了。

32 ~ 36 字节已确认

分别使用3个指针表示发送端的滑动窗口:

img
  • SND.WND:表示发送窗口的大小(大小是由接收方指定的);
  • SND.UNA(Send Unacknoleged):是一个绝对指针,它指向的是已发送但未收到确认的第一个字节的序列号,也就是 #2 的第一个字节。
  • SND.NXT:也是一个绝对指针,它指向未发送但可发送范围的第一个字节的序列号,也就是 #3 的第一个字节。
  • 指向 #4 的第一个字节是个相对指针,它需要 SND.UNA 指针加上 SND.WND 大小的偏移量,就可以指向 #4 的第一个字节了。

那么可用窗口大小的计算就可以是:

可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)

接收方的滑动窗口

接收窗口

  • #1 + #2 是已成功接收并确认的数据(等待应用进程读取);
  • #3 是未收到数据但可以接收的数据;
  • #4 未收到数据并不可以接收的数据;

其中三个接收部分,使用两个指针进行划分:

  • RCV.WND:表示接收窗口的大小,它会通告给发送方。
  • RCV.NXT:是一个指针,它指向期望从发送方发送来的下一个数据字节的序列号,也就是 #3 的第一个字节。
  • 指向 #4 的第一个字节是个相对指针,它需要 RCV.NXT 指针加上 RCV.WND 大小的偏移量,就可以指向 #4 的第一个字节了。

接收窗口和发送窗口的大小是相等的吗?

并不是完全相等,接收窗口的大小是约等于发送窗口的大小的。

3.3.3、流量控制

发送方不能无脑的发数据给接收方,要考虑接收方处理能力。

为了解决这种现象发生,TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。

当操作系统主动调整缓冲区的大小,会发生什么?

当接收方繁忙,操作系统可能会直接减少接收缓冲区的大小,这时应用程序若无法及时读取缓冲数据,会出现数据包丢失的现象。

如果发生了先减少缓存,再收缩窗口,就会出现丢包的现象。

为了防止这种情况发生,TCP 规定是不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存,这样就可以避免了丢包情况。

窗口关闭

TCP 通过让接收方指明希望从发送方接收的数据大小(窗口大小)来进行流量控制。

如果窗口大小为 0 时,就会阻止发送方给接收方传递数据,直到窗口变为非 0 为止,这就是窗口关闭。

窗口关闭存在的问题:窗口关闭后,当接收端处理完数据后,会向发送方重新发送一个窗口非0的ACK报文请求继续发送数据,若此时这个ACK报文丢失,发送方会一直认为接收方窗口为0,持续等待,造成死锁。

解决方法:TCP发送方收到0窗口的通知,会启动持续定时器,如果持续计时器超时,就会发送窗口探测报文,接收方确认报文时,会给出自己当前窗口大小。窗口探测的次数一般为 3 次,每次大约 30-60 秒(不同的实现可能会不一样)。如果 3 次过后接收窗口还是 0 的话,有的 TCP 实现就会发 RST 报文来中断连接。

3.3.4、拥塞控制

流量控制是避免「发送方」的数据填满「接收方」的缓存。

拥塞控制的目的就是避免「发送方」的数据填满整个网络。

为了在「发送方」调节所要发送数据的量,定义了一个叫做「拥塞窗口」的概念。

拥塞窗口

拥塞窗口 cwnd是发送方维护的一个的状态变量,它会根据网络的拥塞程度动态变化的

拥塞窗口 cwnd 变化的规则:

  • 只要网络中没有出现拥塞,cwnd 就会增大;
  • 但网络中出现了拥塞,cwnd 就减少;

问:怎么知道当前网络是否出现了拥塞呢?

答:其实只要「发送方」没有在规定时间内接收到 ACK 应答报文,也就是发生了超时重传,就会认为网络出现了拥塞。

问:拥塞窗口和发送窗口有什么关系呢?

答:我们在前面提到过发送窗口 swnd 和接收窗口 rwnd 是约等于的关系,那么由于加入了拥塞窗口的概念后,此时发送窗口的值是swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值。

拥塞控制主要是四个算法:

  • 慢启动
  • 拥塞避免
  • 拥塞发生
  • 快速恢复

慢启动

TCP 刚刚建立连接完成后,有一个慢启动的过程,一点一点的提高发送数据包的数量,即当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。

有一个叫慢启动门限 ssthresh (slow start threshold)状态变量。

  • cwnd < ssthresh 时,使用慢启动算法。
  • cwnd >= ssthresh 时,就会使用「拥塞避免算法」。

下面举个栗子:

  • 连接建立完成后,一开始初始化 cwnd = 1,表示可以传一个 MSS 大小的数据。
  • 当收到一个 ACK 确认应答后,cwnd 增加 1,于是一次能够发送 2 个
  • 当收到 2 个的 ACK 确认应答后, cwnd 增加 2,于是就可以比之前多发2 个,所以这一次能够发送 4 个
  • 当这 4 个的 ACK 确认到来的时候,每个确认 cwnd 增加 1, 4 个确认 cwnd 增加 4,于是就可以比之前多发 4 个,所以这一次能够发送 8 个。

慢启动算法的变化过程如下图:

img

可以看出慢启动算法,发包的个数是指数性的增长

拥塞避免

拥塞避免算法的规则是:每当收到一个 ACK 时,cwnd 增加 1/cwnd。

发包的个数是线性的增长

拥塞避免

拥塞发生

当网络出现拥塞,也就是会发生数据包重传,重传机制主要有两种:

  • 超时重传
  • 快速重传

这两种使用的拥塞发送算法是不同的。

发生超时重传的拥塞发生算法

这个时候,ssthresh 和 cwnd 的值会发生变化:

  • ssthresh 设为 cwnd/2
  • cwnd 重置为 1 (是恢复为 cwnd 初始化值,我这里假定 cwnd 初始化值 1)

接着,就重新开始慢启动,慢启动是会突然减少数据流的。

拥塞发送 —— 超时重传

发生快速重传的拥塞发生算法

TCP 认为这种情况不严重,因为大部分没丢,只丢了一小部分,则 ssthreshcwnd 变化如下:

  • cwnd = cwnd/2 ,也就是设置为原来的一半;
  • ssthresh = cwnd;

接着,进入快速恢复算法。

快速恢复

快速重传和快速恢复算法一般同时使用,快速恢复算法是认为,你还能收到 3 个重复 ACK 说明网络也不那么糟糕,所以没有必要像 RTO 超时那么强烈。

正如前面所说,进入快速恢复之前,cwndssthresh 已被更新了:

  • cwnd = cwnd/2 ,也就是设置为原来的一半;
  • ssthresh = cwnd;

然后,进入快速恢复算法如下:

  • 拥塞窗口 cwnd = ssthresh + 3 ( 3 的意思是确认有 3 个数据包被收到了);
  • 重传丢失的数据包;
  • 如果再收到重复的 ACK,那么 cwnd 增加 1;
  • 如果收到新数据的 ACK 后,把 cwnd 设置为第一步中的 ssthresh 的值,原因是该 ACK 确认了新的数据,说明从 duplicated ACK 时的数据都已收到,该恢复过程已经结束,可以回到恢复之前的状态了,也即再次进入拥塞避免状态;
快速重传和快速恢复

3.3、如何理解是 TCP 面向字节流协议?

TCP 是面向字节流的协议,UDP 是面向报文的协议

为什么 UDP 是面向报文的协议?

当用户消息通过 UDP 协议传输时,操作系统不会对消息进行拆分,在组装好 UDP 头部后就交给网络层来处理,所以发出去的 UDP 报文中的数据部分就是完整的用户消息,也就是每个 UDP 报文就是一个用户消息的边界,这样接收方在接收到 UDP 报文后,读一个 UDP 报文就能读取到完整的用户消息。

为什么 TCP 是面向字节流的协议?

当用户消息通过 TCP 协议传输时,消息可能会被操作系统分组成多个的 TCP 报文,也就是一个完整的用户消息被拆分成多个 TCP 报文进行传输。

这时,接收方的程序如果不知道发送方发送的消息的长度,也就是不知道消息的边界时,是无法读出一个有效的用户消息的,因为用户消息被拆分成多个 TCP 报文后,并不能像 UDP 那样,一个 UDP 报文就能代表一个完整的用户消息。

因此,我们不能认为一个用户消息对应一个 TCP 报文,正因为这样,所以 TCP 是面向字节流的协议

如何解决TCP粘包?

一般有三种方式分包的方式:

  • 固定长度的消息:例如规定数据长度为64字节,当接收方收满64字节,就认为内容是一个完整的消息。
  • 特殊字符作为边界:在两个用户消息之间插入一个特殊的字符串,这样接收方在接收数据时,读到了这个特殊字符,就把认为已经读完一个完整的消息。
  • 自定义消息结构:自定义一个消息结构,由包头和数据组成,其中包头包是固定大小的,而且包头里有一个字段来说明紧随其后的数据有多大。

3.4、TCP 有什么缺陷

主要有四个方面:

  • 升级 TCP 的工作很困难;
  • TCP 建立连接的延迟;
  • TCP 存在队头阻塞问题;
  • 网络迁移需要重新建立 TCP 连接;

升级TCP的工作很困难

TCP 协议是在内核中实现的,应用程序只能使用不能修改,如果要想升级 TCP 协议,那么只能升级内核。

由于内核升级涉及到底层软件和运行库的更新,我们的服务程序就需要回归测试是否兼容新的内核版本。

TCP建立连接的延迟

基于 TCP 实现的应用协议,都是需要先建立三次握手才能进行数据传输,比如 HTTP 1.0/1.1、HTTP/2、HTTPS。

现在大多数网站都是使用 HTTPS 的,这意味着在 TCP 三次握手之后,还需要经过 TLS 四次握手后,才能进行 HTTP 数据的传输,这在一定程序上增加了数据传输的延迟。

TCP存在队头阻塞问题

TCP 是字节流协议,TCP 层必须保证收到的字节数据是完整且有序的,如果序列号较低的 TCP 段在网络传输中丢失了,即使序列号较高的 TCP 段已经被接收了,应用层也无法从内核中读取到这部分数据。只有等到 丢失的数据包 重传后,接收方的应用层才可以从内核中读取到数据。

HTTP/2 多个请求是跑在一个 TCP 连接中的,那么当 TCP 丢包时,整个 TCP 都要等待重传,那么就会阻塞该 TCP 连接中的所有请求,所以 HTTP/2 队头阻塞问题就是因为 TCP 协议导致的。

发送窗口的队头阻塞

TCP 发送出去的数据,都是需要按序确认的,只有在数据都被按顺序确认完后,发送窗口才会往前滑动。

举个例子,比如下图的发送方把发送窗口内的数据全部都发出去了,可用窗口的大小就为 0 了,表明可用窗口耗尽,在没收到 ACK 确认之前是无法继续发送数据了。

接着,当发送方收到对第 32~36 字节的 ACK 确认应答后,则滑动窗口往右边移动 5 个字节,因为有 5 个字节的数据被应答确认,接下来第 52~56 字节又变成了可用窗口,那么后续也就可以发送 52~56 这 5 个字节的数据了。

32 ~ 36 字节已确认

但是如果某个数据报文丢失或者其对应的 ACK 报文在网络中丢失,会导致发送方无法移动发送窗口,这时就无法再发送新的数据,只能超时重传这个数据报文,直到收到这个重传报文的 ACK,发送窗口才会移动,继续后面的发送行为。

接收窗口的队头阻塞

接收方收到的数据范围必须在接收窗口范围内,如果收到超过接收窗口范围的数据,就会丢弃该数据,比如下图接收窗口的范围是 32 ~ 51 字节,如果收到第 52 字节以上数据都会被丢弃。

接收窗口

接收窗口什么时候才能滑动?当接收窗口收到有序数据时,接收窗口才能往前滑动,然后那些已经接收并且被确认的「有序」数据就可以被应用层读取。

但是,当接收窗口收到的数据不是有序的,比如收到第 33~40 字节的数据,由于第 32 字节数据没有收到, 接收窗口无法向前滑动,那么即使先收到第 33~40 字节的数据,这些数据也无法被应用层读取的。只有当发送方重传了第 32 字节数据并且被接收方收到后,接收窗口才会往前滑动,然后应用层才能从内核读取第 32~40 字节的数据。

因此,

  • 停留「发送窗口」会使得发送方无法继续发送数据。
  • 停留「接收窗口」会使得应用层无法读取新的数据。

网络迁移需要重新建立TCP连接

基于 TCP 传输协议的 HTTP 协议,由于是通过四元组(源 IP、源端口、目的 IP、目的端口)确定一条 TCP 连接。

TCP 四元组

那么当移动设备的网络从 4G 切换到 WIFI 时,意味着 IP 地址变化了,那么就必须要断开连接,然后重新建立 TCP 连接

而建立连接的过程包含 TCP 三次握手和 TLS 四次握手的时延,以及 TCP 慢启动的减速过程,给用户的感觉就是网络突然卡顿了一下,因此连接的迁移成本是很高的。

3.5、基于UDP协议实现可靠传输

基于 UDP 协议实现的可靠传输协议就是 QUIC 协议,已经应用在了 HTTP/3。

QUIC如何实现可靠传输

要基于 UDP 实现的可靠传输协议,那么就要在应用层下功夫,也就是要设计好协议的头部字段。

拿 HTTP/3 举例子,在 UDP 报文头部与 HTTP 消息之间,共有 3 层头部:

img

整体看的视角是这样的:

img

接下来,分别对每一个 Header 做个介绍。

Packet Header

Packet Header 首次建立连接时和日常传输数据时使用的 Header 是不同的。如下图(注意我没有把 Header 所有字段都画出来,只是画出了重要的字段):

Packet Header

Packet Header 细分这两种:

  • Long Packet Header 用于首次建立连接。
  • Short Packet Header 用于日常传输数据。

QUIC 也是需要三次握手来建立连接的,主要目的是为了协商连接 ID。协商出连接 ID 后,后续传输时,双方只需要固定住连接 ID,从而实现连接迁移功能。所以,你可以看到日常传输数据的 Short Packet Header 不需要在传输 Source Connection ID 字段了,只需要传输 Destination Connection ID。

Short Packet Header 中的 Packet Number 是每个报文独一无二的编号,它是严格递增的,也就是说就算 Packet N 丢失了,重传的 Packet N 的 Packet Number 已经不是 N,而是一个比 N 大的值。

img

Packet Number 单调递增的两个好处:

  • 可以更加精确计算 RTT,没有 TCP 重传的歧义性问题:可以由服务端ACK确认是「原始报文的响应」还是「重传报文的响应」,从而精确计算RTT(报文往返时间),进而精确计算RTO(超时时间)。
  • 可以支持乱序确认,只要有新的已接受数据包确认,当前窗口就会继续向右滑动,而 TCP 必须是顺序确认的,丢包时会导致窗口不滑动;
QUIC Frame Header

一个 Packet 报文中可以存放多个 QUIC Frame。

每一个 Frame 都有明确的类型,针对类型的不同,功能也不同,自然格式也不同。

4、IP

IP 和 MAC 的区别

MAC地址:物理地址,每个网卡出厂后MAC地址固定;使数据从一个节点传递到相同链路的另一个节点上。

IP地址:接入互联网中计算机的地址;使数据可以从一个网络传递到另一个网络上。

MAC 的作用则是实现「直连」的两个设备之间通信,而 IP 则负责在「没有直连」的两个网络之间进行通信传输。

IP 的作用与 MAC 的作用

4.1、IP 地址分类

IP 地址分类成了 5 种类型,分别是 A 类、B 类、C 类、D 类、E 类。

IP 地址分类

什么是 A、B、C 类地址?

img

最大主机个数,就是要看主机号的位数,如 C 类地址的主机号占 8 位,那么 C 类地址的最大主机个数:

img

为什么要减 2 呢?

因为在 IP 地址中,有两个 IP 是特殊的,分别是主机号全为 1 和 全为 0 地址。

4.2、无分类地址CIDR

IP 地址缺点:

  • 没有地址层次:一个公司可能需要根据生产环境、测试环境、开发环境划分地址,IP分类没有这个功能
  • 不能很好与现实网络匹配:例如C类IP地址只有254个,一个网吧都不够用。

CIDR

CIDR:不再对IP进行分类,即IP地址直接被划分为两部分 网络号 + 主机号。

表示形式 a.b.c.d/x,其中 /x 表示前 x 位属于网络号, x 的范围是 0 ~ 32,这就使得 IP 地址更加具有灵活性。

比如 10.100.122.2/24,这种地址表示形式就是 CIDR,/24 表示前 24 位是网络号,剩余的 8 位是主机号。

img

4.3、IP地址与路由控制

在发送 IP 包时,首先要确定 IP 包首部中的目标地址,再从路由控制表中找到与该地址具有相同网络地址的记录,根据该记录将 IP 包转发给相应的下一个路由器。如果路由控制表中存在多条相同网络地址的记录,就选择相同位数最多的网络地址,也就是最长匹配。

IP 地址与路由控制

  1. 主机 A 要发送一个 IP 包,其源地址是 10.1.1.30 和目标地址是 10.1.2.10,由于没有在主机 A 的路由表找到与目标地址 10.1.2.10 相同的网络地址,于是包被转发到默认路由(路由器 1
  2. 路由器 1 收到 IP 包后,也在路由器 1 的路由表匹配与目标地址相同的网络地址记录,发现匹配到了,于是就把 IP 数据包转发到了 10.1.0.2 这台路由器 2
  3. 路由器 2 收到后,同样对比自身的路由表,发现匹配到了,于是把 IP 包从路由器 210.1.2.1 这个接口出去,最终经过交换机把 IP 数据包转发到了目标主机

4.4、IP 分片与重组

每种数据链路的最大传输单元 MTU 都是不相同的,如 FDDI 数据链路 MTU 4352、以太网的 MTU 是 1500 字节等。

当 IP 数据包大小大于 MTU 时, IP 数据包就会被分片。

经过分片之后的 IP 数据报在被重组的时候,只能由目标主机进行,路由器是不会进行重组的。

4.5、IP 协议相关技术

DNS 域名解析

DNS 可以将域名网址自动转换为具体的 IP 地址。

ARP 地址解析协议

根据IP地址获取MAC物理地址

RARP 协议:已知 MAC 地址求 IP 地址

DHCP 动态主机配置协议

使网络环境中的主机动态的获得IP地址

NAT

网络地址转换技术,把私有 IP 地址转换成公有 IP 地址。

ICMP 互联网控制报文协议

当网络包在传输遇到问题的时候,传出消息。

常见知识点

1.应用层常见协议

HTTP:HyperText Transfer Protocol 超文本传输协议

Web浏览器与Web服务器之间通信

HTTP请求 -----HTTP响应

HTTP1.1默认长连接,即Keep-Alive,建立的连接可以在多次请求中复用

SMTP:Sample Mail Transfer Protocol 简单邮件传输协议

仅用来发送邮件

接收邮件使用POP3/IMAP协议

FTP:File Transfer Protocol 文件传输协议

特点:建立两条连接,即

  • 控制连接:用于传送控制信息
  • 数据连接:用于数据传送

Telnet:远程登陆协议

所有数据均以明码形式发送,因此不安全

SSH:安全的网络传输协议

对传输的数据进行加密,保证数据的安全性

2.TCP三次握手和四次挥手

1.三次握手

三次握手

  • 客户端–发送带有 SYN 标志的数据包–一次握手–服务端
  • 服务端–发送带有 SYN/ACK 标志的数据包–二次握手–客户端
  • 客户端–发送带有 ACK 标志的数据包–三次握手–服务端

三次握手,保证双方接收数据和发送数据均正常。

第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常

第二次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:对方发送正常,自己接收正常

第三次握手:Client 确认了:自己发送、接收正常,对方发送、接收正常;Server 确认了:自己发送、接收正常,对方发送、接收正常

第 2 次握手传回了 ACK,为什么还要传回 SYN?

接收端传回发送端所发送的 ACK 是为了告诉客户端,我接收到的信息确实就是你所发送的信号了,这表明从客户端到服务端的通信是正常的。而回传 SYN 则是为了建立并确认从服务端到客户端的通信。

2.四次挥手

三次握手

3.TCP、UDP协议区别

UDP

  • 在传送数据之前不需要先建立连接,远地主机在收到 UDP 报文后,不需要给出任何确认。
  • 在即时通信中,是一种最有效的工作方式。

TCP

  • 提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。
  • 由于 TCP 要提供可靠的,面向连接的传输服务,这难以避免增加了许多开销。

4.在浏览器中输入 url 地址 ->> 显示主页的过程

简单的网络模型

1、HTTP解析url,生成请求消息

image-20220705174927610

请求消息格式:

image-20220705175109986

2、DNS域名解析:

浏览器自身缓存 ===> 操作系统缓存 ===> 本地host文件 ===> 本地DNS服务器查询

本地DNS查询流程:

域名解析的工作流程

3、协议栈

1、TCP协议传输:

TCP 层报文

2、IP协议传输:

IP 层报文

4、两点传输——MAC

生成了 IP 头部之后,接下来网络包还需要在 IP 头部的前面加上 MAC 头部

MAC 包头格式

MAC报文格式:

MAC 层报文

5、出口 —— 网卡

数字信息转换为电信号,在网线上传输。

6、送别者 —— 交换机

将接收的所有网络包以广播的形式发送给所有端口。

因为交换机不具备MAC地址,所以无法判断数据是不是发给自己的。

7、出境大门 —— 路由器

路由器具备 IP地址 和 MAC地址。

将发给自己的包的数据转发给下一个路由器或者自己的服务器。

8、服务器

到达服务器的数据,反向差分获得HTTP请求,然后将资源包装成数据包再发送给客户端,完成一次通信。

5.Cookie 的作用是什么? 和 Session 有什么区别?

Cookie 一般用来保存用户信息

① 我们在 Cookie 中保存已经登录过的用户信息,下次访问网站的时候页面可以自动帮你把登录的一些基本信息给填了;

② 一般的网站都会有保持登录,也就是说下次你再访问网站的时候就不需要重新登录了

Session 的主要作用就是通过服务端记录用户的状态。

服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了。

Cookie 数据保存在客户端(浏览器端),Session 数据保存在服务器端。

6.URI 和 URL 的区别是什么?

  • URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
  • URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。
posted @ 2022-11-28 17:38  柯文先生  阅读(289)  评论(0)    收藏  举报