网络部分

HTTP

HTTP协议是个无状态协议,不会保存状态 3.1 Post 和 Get 的区别

  • Get请求能缓存,Post不能
  • Post相对Get安全一点点,因为Get请求都包含在URL里,且会被浏览器保存历史纪录,Post不会,但是在抓包的情况下都是一样的。
  • Post可以通过request body来传输比Get更多的数据,Get没有这个技术
  • URL有长度限制,会影响Get请求,但是这个长度限制是浏览器规定的,不是RFC规定的
  • Post支持更多的编码类型且不对数据类型限制 3.2 常见状态码 2XX 成功
  • 200 OK,表示从客户端发来的请求在服务器端被正确处理
  • 204 No content,表示请求成功,但响应报文不含实体的主体部分
  • 205 Reset Content,表示请求成功,但响应报文不含实体的主体部分,但是与204响应不同在于要求请求方重置内容
  • 206 Partial Content,进行范围请求 3XX 重定向
  • 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL
  • 302 found,临时性重定向,表示资源临时被分配了新的 URL
  • 303 see other,表示资源存在着另一个 URL,应使用 GET 方法丁香获取资源
  • 304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况
  • 307 temporary redirect,临时重定向,和 302 含义类似,但是期望客户端保持请求方法不变向新的地址发出请求 4XX 客户端错误
  • 400 bad request,请求报文存在语法错误
  • 401 unauthorized,表示发送的请求需要有通过HTTP认证的认证信息
  • 403 forbidden,表示对请求资源的访问被服务器拒绝
  • 404 not found,表示在服务器上没有找到请求的资源 5XX 服务器错误
  • 500 internal sever error,表示服务器端在执行请求时发生了错误
  • 501 Not Implemented,表示服务器不支持当前请求所需要的某个功能
  • 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-Length request body长度
Content-Location 返回数据的备用地址
Content-MD5 Base64加密格式的内容MD5检验值
Content-Range 内容的位置范围
Content-Type 内容的媒体类型
Expires 内容的过期时间
Last_modified 内容的最后修改时间

TCP

2.1 头部

TCP头部比UDP头部复杂的多 对于TCP头部来说,以下几个字段是很重要的

  • Sequence number,这个序号保证了TCP传输的报文都是有序的,对端可以通过序号顺序的拼接报文
  • Acknowledgement Number,这个序号表示数据接收端期望接收的下一个字节的编号是多少,同时也表示上一个序号的数据已经收到
  • Window Size,窗口大小,表示还能接收多少字节的数据,用于流量控制 标识符
  • URG=1:该字段为一表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效。紧急数据一定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。
  • ACK=1:该字段为一表示确认号字段有效。此外,TCP还规定在连接建立后传送的所有报文段都必须把ACK置为一PSH=1:该字段为一表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。
  • RST=1:该字段为一表示当前TCP连接出现严重问题,可能需要重新建立TCP连接,也可以用于拒绝非法的报文段和拒绝连接请求。
  • SYN=1:当SYN=1ACK=0时,表示当前报文段是一个连接请求报文。当SYN=1ACK=1时,表示当前报文段是一个同意建立连接的应答报文。
  • FIN=1:该字段为一表示此报文段是一个释放连接的请求报文 2.2 状态机

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

  • TCP的状态机是很复杂的,并且与建立断开连接时的握手息息相关,接下来就来详细描述下两种握手。
  • 在这之前需要了解一个重要的性能指标 RTT。该指标表示发送端发送数据到接收到对端数据所需的往返时间 建立连接三次握手
  • TCP协议中,主动发起请求的一端为客户端,被动连接的一端称为服务端。不管是客户端还是服务端,TCP连接建立完后都能发送和接收数据,所以TCP也是一个全双工的协议。
  • 起初,两端都为CLOSED状态。在通信开始前,双方都会创建TCB。 服务器创建完TCB后遍进入LISTEN状态,此时开始等待客户端发送数据 第一次握手

    客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入 SYN-SENT 状态,x 表示客户端的数据通信初始序号。 第二次握手 服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入SYN-RECEIVED状态。 第三次握手 当客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接建立成功。

  • PS:第三次握手可以包含数据,通过TCP快速打开(TFO)技术。其实只要涉及到握手的协议,都可以使用类似TFO的方式,客户端和服务端存储相同cookie,下次握手时发出cookie达到减少RTT的目的 你是否有疑惑明明两次握手就可以建立起连接,为什么还需要第三次应答?
  • 因为这是为了防止失效的连接请求报文段被服务端接收,从而产生错误

    可以想象如下场景。客户端发送了一个连接请求 A,但是因为网络原因造成了超时,这时 TCP 会启动超时重传的机制再次发送一个连接请求 B。此时请求顺利到达服务端,服务端应答完就建立了请求。如果连接请求 A 在两端关闭后终于抵达了服务端,那么这时服务端会认为客户端又需要建立 TCP 连接,从而应答了该请求并进入ESTABLISHED状态。此时客户端其实是 CLOSED 状态,那么就会导致服务端一直等待,造成资源的浪费 PS:在建立连接中,任意一端掉线,TCP 都会重发 SYN 包,一般会重试五次,在建立连接中可能会遇到 SYN FLOOD 攻击。遇到这种情况你可以选择调低重试次数或者干脆在不能处理的情况下拒绝请求 断开链接四次握手 > TCP是全双工的,在断开连接时两端都需要发送FINACK第一次握手 若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。 第二次握手 B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,表示 A 到 B 的连接已经释放,不接收 A 发的数据了。但是因为 TCP 连接时双向的,所以 B 仍旧可以发送数据给 A。 第三次握手 B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入 LAST-ACK 状态。 PS:通过延迟确认的技术(通常有时间限制,否则对方会误认为需要重传),可以将第二次和第三次握手合并,延迟 ACK 包的发送。 第四次握手

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

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

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

UDP

1.1 面向报文

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

  • 在发送端,应用层将数据传递给传输层的UDP协议,UDP只会给数据增加一个UDP头标识下是UDP协议,然后就传递给网络层了
  • 在接收端,网络层将数据传递给传输层,UDP只去除IP报文头就传递给应用层,不会任何拼接操作 1.2 不可靠性
  • UDP是无连接的,也就是说通信不需要建立和断开连接。
  • UDP也是不可靠的。协议收到什么数据就传递什么数据,并且也不会备份数据,对方能不能收到是不关心的
  • UDP没有拥塞控制,一直会以恒定的速度发送数据。即使网络条件不好,也不会对发送速率进行调整。这样实现的弊端就是在网络条件不好的情况下可能会导致丢包,但是优点也很明显,在某些实时性要求高的场景(比如电话会议)就需要使用 UDP 而不是TCP 1.3 高效
  • 因为UDP没有TCP那么复杂,需要保证数据不丢失且有序到达。所以UDP的头部开销小,只有八字节,相比TCP的至少二十字节要少得多,在传输数据报文时是很高效的 头部包含了以下几个数据
  • 两个十六位的端口号,分别为源端口(可选字段)和目标端口 整个数据报文的长度
  • 整个数据报文的检验和(IPv4可选 字段),该字段用于发现头部信息和数据中的错误 1.4 传输方式

    UDP不止支持一对一的传输方式,同样支持一对多,多对多,多对一的方式,也就是说 UDP 提供了单播,多播,广播的功能

DNS

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

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

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

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

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

WebSocket

由于http存在一个明显的弊端(消息只能有客户端推送到服务器端,而服务器端不能主动推送到客户端),导致如果服务器如果有连续的变化,这时只能使用轮询,而轮询效率过低,并不适合。于是WebSocket被发明出来 相比与http具有以下有点

  • 支持双向通信,实时性更强;
  • 可以发送文本,也可以二进制文件;
  • 协议标识符是ws,加密后是wss
  • 较少的控制开销。连接创建后,ws客户端、服务端进行数据交换时,协议控制的数据包头部较小。在不包含头部的情况下,服务端到客户端的包头只有2~10字节(取决于数据包长度),客户端到服务端的的话,需要加上额外的 4 字节的掩码。而HTTP协议每次通信都需要携带完整的头部;
  • 支持扩展。ws 协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议。(比如支持自定义压缩算法等)
  • 无跨域问题。

    实现比较简单,服务端库如socket.iows,可以很好的帮助我们入门。而客户端也只需要参照api实现即可