Skip to content

网络

1. UDP

1.1 面向报文

UDP 是⼀个面向报⽂ (报⽂可以理解为⼀段段的数据) 的协议 。意思就是 UDP 只是报⽂的搬运⼯,不会对报⽂进行任何拆分和拼接操作

具体来说

  1. 在发送端,应用层将数据传递给传输层的 UDP 协议, UDP 只会给数据增加⼀个 UDP 头标识下是 UDP 协议,然后就传递给网络层了
  2. 在接收端, 网络层将数据传递给传输层, UDP 只去除 IP 报⽂头就传递给应用层,不会任何拼接操作

1.2 不可靠性

  1. UDP 是⽆连接的,也就是说通信不需要建立和断开连接。
  2. UDP 也是不可靠的 。协议收到什么数据就传递什么数据, 并且也不会备份数据,对⽅能不能收到是不关⼼的
  3. UDP 没有拥塞控制,⼀ 直会以恒定的速度发送数据 。即使网络条件不好,也不会对发送速率进行调整 。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景 ( 比如电话会议) 就需要使用 UDP 而不是 TCP

1.3 高效

因为 UDP 没有 TCP 那么复杂, 需要保证数据不丢失且有序到达 。所以 UDP 的头部开销⼩,只有⼋字节,相比 TCP 的至少⼆⼗字节要少得多,在传输数据报⽂时是很高效的

头部包含了以下几个数据

  • 两个⼗六位的端⼝号 ,分别为源端⼝ ( 可选字段) 和目标端⼝ 整个数据报⽂的长度
  • 整个数据报⽂的检验和 ( IPv4 可选 字段), 该字段用于发现头部信息和数据中的错误

1.4 传输方式

UDP 不止⽀持⼀对⼀的传输⽅式, 同样⽀持⼀对多, 多对多, 多对⼀的⽅式,也就是说 UDP 提供了单播, 多播,⼴播的功能

2. TCP

2.1 头部

TCP 头部比 UDP 头部复杂的多

对于 TCP 头部来说, 以下⼏个字段是很重要的:

  1. Sequence number , 这个序号保证了 TCP 传输的报⽂都是有序的,对端可以通过序号顺序的拼接报⽂
  2. Acknowledgement Number , 这个序号表示数据接收端期望接收的下⼀个字节的编号是多少, 同时也表示上⼀个序号的数据已经收到
  3. Window Size , 窗⼝大⼩ ,表示还能接收多少字节的数据,用于流量控制

标识符

  1. URG=1 :该字段为⼀表示本数据报的数据部分包含紧急信息, 是⼀个高优先级数据报⽂,此时紧急指针有效 。紧急数据⼀定位于当前数据包数据部分的最前面, 紧急指针标明了紧急数据的尾部。
  2. ACK=1 :该字段为⼀表示确认号字段有效 。此外, TCP 还规定在连接建立后传送的所有报⽂段都必须把 ACK 置为⼀ PSH=1 :该字段为⼀表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。
  3. RST=1 :该字段为⼀表示当前 TCP 连接出现严重问题, 可能需要重新建立 TCP 连接,也可以用于拒绝非法的报⽂段和拒绝连接请求。
  4. SYN=1 : 当 SYN=1ACK=0 时,表示当前报⽂段是⼀个连接请求报⽂ 。当 SYN=1ACK=1 时,表示当前报⽂段是⼀个同意建立连接的应答报⽂ 。
  5. FIN=1 :该字段为⼀表示此报⽂段是⼀个释放连接的请求报⽂

2.2 状态机

HTTP 是⽆连接的,所以作为下层的 TCP 协议也是⽆连接的, 虽然看似 TCP 将两端连接了起来,但是其实只是两端共同维护了⼀个状态

TCP 的状态机是很复杂的, 并且与建立断开连接时的握手息息相关,接下来就来详细描述下两种握手。

在这之前需要了解⼀个重要的性能指标 RTT 。该指标表示发送端发送数据到接收到对端数据所需的往返时间

建立连接三次握手

TCP 协议中, 主动发起请求的⼀端为客户端,被动连接的⼀端称为服务端 。不管是客户端还是服务端, TCP 连接建立完后都能发送和接收数据,所以 TCP 协议。 起初,两端都为 CLOSED 状态 。在通信开始前, 双⽅都会创建 TCBTCB 后遍进⼊ LISTEN 状态, 此时开始等待客户端发送数据

  1. 第⼀次握手

客户端向服务端发送连接请求报⽂段 。该报⽂段中包含自身的数据通讯初始序号 。请求发送后,客户端便进⼊ SYN-SENT 状态,x 表示客户端的数据通信初始序号。

  1. 第二次握手

服务端收到连接请求报⽂段后,如果同意连接,则会发送⼀个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进⼊ SYN-RECEIVED 状态。

  1. 第三次握手

当客户端收到连接同意的应答后, 还要向服务端发送⼀个确认报⽂ 。客户端发完这个报⽂段后便进⼊ ESTABLISHED 状态, 服务端收到这个应答后也进⼊ ESTABLISHED 状态,此时连接建立成功。

PS:第三次握⼿可以包含数据, 通过 TCP 快速打开 ( TFO ) 技术 。其实只要涉及到握 ⼿的协议,都可以使用类似 TFO 的⽅式,客户端和服务端存储相同 cookie ,下次握⼿ 时发出 cookie 达到减少 RTT 的目的

你是否有疑惑明明两次握手就可以建立起连接,为什么还需要第三次应答?

因为这是为了防止失效的连接请求报⽂段被服务端接收,从而产生错误

可以想象如下场景 。客户端发送了⼀个连接请求 A ,但是因为网络原因造成了超时, 这时 TCP 会启动超时重传的机制再次发送⼀个连接请求 B 。此时请求顺利到达服务端, 服务端应答完就建立了请求 。如果连接请求 A 在两端关闭后终于抵达了服务端,那么这时服务端会认为客户端⼜需要建立 TCP 连接,从而应答了该请求并进⼊ ESTABLISHED 状态 。此时客户端其实是 CLOSED 状态,那么就会导致服务端⼀直等待, 造成资源的浪费

PS:在建立连接中,任意⼀端掉线,TCP 都会重发 SYN 包,⼀般会重试五次,在建立连接中可能会遇到 SYN FLOOD 攻击 。遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求

断开链接四次握手

TCP 是全双⼯的,在断开连接时两端都需要发送 FINACK

  1. 第⼀次握手

若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。

  1. 第二次握手

B 收到连接释放请求后,会告诉应用层要释放 TCP 链接 。然后会发送 ACK 包, 并进⼊ CLOSE_WAIT 状态,表示 AB 的连接已经释放,不接收 A 发的数据了 。但是因为 TCP 连接时双向的,所以 B 仍旧可以发送数据给 A

  1. 第三次握手

B 如果此时还有没发完的数据会继续发送, 完毕后会向 A 发送连接释放请求,然后 B 便进⼊ LAST-ACK 状态。

PS:通过延迟确认的技术 ( 通常有时间限制, 否则对⽅会误认为需要重传),可以将第⼆次和第三次握⼿合并,延迟 ACK 包的发送。

  1. 第四次握手

A 收到释放请求后, 向 B 发送确认应答,此时 A 进⼊ TIME-WAIT 状态 。该状态会持续 2MSL ( 最大段生存期,指报⽂段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进⼊ CLOSED 状态 。当 B 收到确认应答后,也便进⼊ CLOSED 状态。

为什么 A 要进⼊ TIME-WAIT 状态, 等待 2MSL 时间后才进⼊ CLOSED 状态?

为了保证 B 能收到 A 的确认应答 。若 A 发完确认应答后直接进⼊ CLOSED 状态, 如果确认应答因为网络问题⼀直没有到达,那么会造成 B 不能正常关闭

3. HTTP

HTTP 协议是个⽆状态协议,不会保存状态

3.1 Post 和 Get 的区别

  1. Get 请求能缓存, Post 不能
  2. Post 相对 Get 安全⼀点点, 因为 Get 请求都包含在 URL 里,且会被浏览器保存历史纪录, Post 不会,但是在抓包的情况下都是⼀样的。
  3. Post 可以通过 request body 来传输比 Get 更多的数据, Get 没有这个技术
  4. URL 有长度限制,会影响 Get 请求,但是这个长度限制是浏览器规定的,不是 RFC 规定的
  5. Post ⽀持更多的编码类型且不对数据类型限制

3.2 常见状态码

2XX 成功

  1. 200 OK ,表示从客户端发来的请求在服务器端被正确处理
  2. 204 No content ,表示请求成功,但响应报文不含实体的主体部分
  3. 205 Reset Content ,表示请求成功,但响应报文不含实体的主体部分,但是与 204 响应不同在于要求请求方重置内容
  4. 206 Partial Content , 进⾏范围请求

3XX 重定向

  1. 301 moved permanently ,永久性重定向,表示资源已被分配了新的 URL
  2. 302 found , 临时性重定向,表示资源临时被分配了新的 URL
  3. 303 see other ,表示资源存在着另⼀个 URL ,应使用 GET 方法丁香获取资源
  4. 304 not modified ,表示服务器允许访问资源,但因发生请求未满足条件的情况
  5. 307 temporary redirect , 临时重定向,和 302 含义类似,但是期望客户端保持请求方法不变向新的地址发出请求

4XX 客户端错误

  1. 400 bad request ,请求报文存在语法错误
  2. 401 unauthorized ,表示发送的请求需要有通过 HTTP 认证的认证信息
  3. 403 forbidden ,表示对请求资源的访问被服务器拒绝
  4. 404 not found ,表示在服务器上没有找到请求的资源

5XX 服务器错误

  1. 500 internal sever error ,表示服务器端在执⾏请求时发生了错误
  2. 501 Not Implemented ,表示服务器不支持当前请求所需要的某个功能
  3. 503 service unavailable ,表明服务器暂时处于超负载或正在停机维护, 无法处理请求

3.3 HTTP 首部

通用字段作用
Cache-Control控制缓存的行为
Connection浏览器想要优先使用的连接类型, 比如 keep-alive
Date创建报文时间
Pragma报文指令
Via代理服务器相关信息
Transfer-Encoding传输编码方式
Upgrade要求客户端升级协议
Warning在内容中可能存在错误
请求字段作用
Accept能正确接收的媒体类型
Accept-Charset能正确接收的字符集
Accept-Encoding能正确接收的编码格式列表
Accept-Language能正确接收的语⾔列表
Expect期待服务端的指定⾏为
From请求方邮箱地址
Host服务器的域名
If-Match两端资源标记比较
If-Modified-Since本地资源未修改返回 304 ( 比较时间)
If-None-Match本地资源未修改返回 304 ( 比较标记)
User-Agent客户端信息
Max-Forwards限制可被代理及网关转发的次数
Proxy-Authorization向代理服务器发送验证信息
Range请求某个内容的⼀部分
Referer表示浏览器所访问的前⼀个页面
TE传输编码方式
响应字段作用
Accept-Ranges是否支持某些种类的范围
Age资源在代理缓存中存在的时间
ETag资源标识
Location客户端重定向到某个 URL
Proxy-Authenticate向代理服务器发送验证信息
Server服务器名字
WWW-Authenticate获取资源需要的验证信息
实体字段作用
Allow资源的正确请求方式
Content-Encoding内容的编码格式
Content-Language内容使用的语⾔
Content-Lengthrequest body 长度
Content-Location返回数据的备用地址
Content-MD5Base64 加密格式的内容 MD5 检验值
Content-Range内容的位置范围
Content-Type内容的媒体类型
Expires内容的过期时间
Last_modified内容的最后修改时间

4. DNS

DNS 的作用就是通过域名查询到具体的 IP

因为 IP 存在数字和英文的组合 ( IPv6 ), 很不利于⼈类记忆,所以就出现了域名 。你可以把域名看成是某个 IP 的别名, DNS 就是去查询这个别名的真正名称是什么

TCP 握手之前就已经进⾏了 DNS 查询, 这个查询是操作系统自己做的。当你在浏览器中想访问 www.google.com 时,会进⾏⼀下操作

操作系统会首先在本地缓存中查询,没有的话会去系统配置的 DNS 服务器中查询,如果这时候还没得话,会直接去 DNS 根服务器查询, 这⼀步查询会找出负责 com 这个⼀级域名的服务器,然后去该服务器查询 google 这个⼆级域名,接下来三级域名的查询其实是我们配置的,你可以给 www 这个域名配置⼀个 IP ,然后还可以给别的三级域名配置⼀个 IP

以上介绍的是 DNS 迭代查询, 还有种是递归查询, 区别就是前者是由客户端去做请求,后者是由系统配置的 DNS 服务器做请求,得到结果后将数据返回给客户端。