Node.js 网络 HTTP

OSI & TCP/IP 模型设计

协议是什么?
明确定义每部分的作用、职责、类似于规范及约束

OSI 7层模型

OSI七层模型(Open System Interconnection)开放式的系统互联

应用层:(Application Layer)

功能是直接向用户提供服务,完成用户希望在网络上完成的各种工作
文件服务、目录服务、文件传输服务(FTP)、远程登录服务(Telnet)、电子邮件服务(E-mail)、打印服务、安全服务、网络管理服务、数据库服务、DNS服务etc
在应用层交互的数据单元称为报文
主要能力
用户接口:应用层是用户与网络,以及应用程序与网络间的直接接口,使得用户能够与网络进行交互式联系
实现各种服务:该层具有的各种应用程序可以完成和实现用户请求的各种服务

表示层:(Presentation Layer)

对来自应用层的命令和数据进行解释,对各种语法赋予相应的含义,并按照一定的格式传送给会话层。其主要功能是“处理用户信息的表示问题,如编码、数据格式转换和加密解密”
主要能力
数据格式处理:协商和建立数据交换的格式,解决各应用程序之间在数据格式表示上的差异
数据的编码:处理字符集和数字的转换。例如由于用户程序中的数据类型(整型或实型、有符号或无符号等)、用户标识等都可以有不同的表示方式,因此,在设备之间需要具有在不同字符集或格式之间转换的功能
压缩和解压缩:为了减少数据的传输量,这一层还负责数据的压缩与恢复
数据的加密和解密:可以提高网络的安全性

会话层:(Session Layer)

向两个实体的表示层提供建立和使用连接的方法。将不同实体之间的表示层的连接称为会话。因此会话层的任务就是组织和协调两个会话进程之间的通信,并对数据交换进行管理
主要能力
会话管理:允许用户在两个实体设备之间建立、维持和终止会话,并支持它们之间的数据交换。
会话流量控制:提供会话流量控制和交叉会话功能
寻址:使用远程地址建立会话连接。
出错控制:从逻辑上讲会话层主要负责数据交换的建立、保持和终止,但实际的工作却是接收来自传输层的数据,并负责纠正错误。会话控制和远程过程调用均属于这一层的功能。但应注意,此层检查的错误不是通信介质的错误,而是磁盘空间、打印机缺纸等类型的高级错误。

传输层:(Transport Layer)

以下三层:数据通信,以上三层:数据处理,是通信子网和资源子网的接口和桥梁,起到承上启下的作用
向用户提供可靠的端到端的差错和流量控制,保证报文的正确传输,向高层屏蔽下层数据通信的细节,即向用户透明地传送报文,常见的协议:TCP、UDP
主要能力
传输连接管理,在网络层的基础上为高层提供“面向连接”和“面向无接连”的两种服务
处理传输差错。提供可靠的“面向连接”和不太可靠的“面向无连接”的数据传输服务、差错控制和流量控制。在提供“面向连接”服务时,通过这一层传输的数据将由目标设备确认,如果在指定的时间内未收到确认信息,数据将被重发
监控服务质量

网络层:(Network Layer)

通过路由选择算法,为报文或分组通过通信子网选择最适当的路径
数据链路层的数据在这一层被转换为数据包,然后通过路径选择、分段组合、顺序、进/出路由等控制,将信息从一个网络设备传送到另一个网络设备
主要能力
寻址:数据链路层中使用的物理地址(如MAC地址)仅解决网络内部的寻址问题。在不同子网之间通信时,为了识别和找到网络中的设备,每一子网中的设备都会被分配一个唯一的地址。由于各子网使用的物理技术可能不同,因此这个地址应当是逻辑地址(如IP地址)
交换:规定不同的信息交换方式。常见的交换技术有:线路交换技术和存储转发技术,后者又包括报文交换技术和分组交换技术
路由算法:当源节点和目的节点之间存在多条路径时,本层可以根据路由算法,通过网络为数据分组选择最佳路径,并将信息从最合适的路径由发送端传送到接收端
连接服务:与数据链路层流量控制不同的是,前者控制的是网络相邻节点间的流量,后者控制的是从源节点到目的节点间的流量。其目的在于防止阻塞,并进行差错检测。

负责建立和管理节点间的链路
通过各种控制协议,将有差错的物理信道变为无差错的、能可靠传输数据帧的数据链路
接受物理层的数据,封装成帧传给上层,接受上层数据解析成比特数据换发给物理层

物理层:(Physical Layer)

实现计算机节点之间比特流的透明传送
物理层的主要任务描述为确定与传输媒体的接口的一些特性,提供用于建立、保持和断开物理连接的机械的、电气的、功能的和过程的条件,也就是说物理层提供有关同步和比特流在物理媒体上的传输手段。
是物理硬件上的底层能力,比如光缆、电缆等设备连接形成组网
包括信号的调制及信道复用等

TCP/IP协议

1672025854266.jpg

应用层

大多数普通与网络相关的程序为了通过网络与其他程序通信所使用的层。这个层的处理过程是应用特有的;数据从网络相关的程序以这种应用内部使用的格式进行传送,然后被编码成标准协议的格式;
应用层负责处理特定的应用程序细节。包括Telnet(远程登录)、FTP(文件传输协议)、SMTP(简单邮件传送协议)以及SNMP(简单网络管理协议)等;

传输层

两台主机上的应用程序提供端到端的通信,有2种传输协议:TCP(传输控制协议)和UDP(用户数据报协议);

网络层

处理分组在网络中的活动,例如分组的选路。网络层协议包括IP协议(网际协议)、ICMP协议(Internet互联网控制报文协议),以及IGMP协议(Internet组管理协议);

网络接口层

也称作数据链路层,包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。一起处理与电缆(或其他任何传输媒介)的物理接口细节;

OSI与TCP/IP协议间的关系

  • OSI引入了服务、接口、协议、分层的概念,TCP/IP借鉴了OSI的这些概念建立TCP/IP模型;
  • OSI先有模型,后有协议,先有标准,后进行实践;而TCP/IP则相反,先有协议和应用再提出了模型,且是参照的OSI模型;
  • OSI是一种理论下的模型,而TCP/IP已被广泛使用,成为网络互联事实上的标准。

每层间的合作与加工

1672025947509.jpg

TCP&UDP

TCP、UDP区别

  • TCP(Transmission Control Protocol),传输控制协议,是一种可靠、面向字节流的通信协议,把上面应用层交下来的数据看成无结构的字节流来发送,需要20个字节

1672026012505.jpg

  • UDP(User Datagram Protocol),用户数据包协议,是一个简单的面向数据报的通信协议,只是在其上面加上首部后就交给了下面的网络层,只占用8个字节(64bit)

1672026039992.jpg

TCP UDP
是否连接 面向连接 无连接
是否可靠 可靠传输,使用流量控制和拥塞控制 不可靠传输,不使用流量控制和拥塞控制
连接对象个数 只能是一对一通信 支持一对一,一对多,多对一和多对多交互通信
传输方式 面向字节流 面向报文
首部开销 首部最小 20 字节,最大 60 字节 首部开销小,仅 8 字节
适用场景 适用于要求可靠传输的应用,例如文件传输 适用于实时应用(IP 电话、视频会议、直播等)
  • 直播属于那种协议?
    • 直播使用的RTMP、HLS都是基于TCP的;
    • 不是所有流媒体通信都是UDP;

TCP的三次握手、四次挥手

  • 三次握手
    1672026195865.jpg

  • 一起发送消息
    1672026226807.jpg

  • 四次挥手
    1672026241625.jpg

TCP是否每次连接都需要3次握手?

TCP快速打开(TCP Fast Open,TFO)
第一次握手:

  1. SYN在fast open带上cookie
  2. 服务端产生cookie,在ACK返回改cookie给客户端
  3. 客户端存储cookie
    以后:
  4. 客户端带有cookie
  5. 服务端验证该cookie,有效,在返回ACK的同时,将数据直接返回给应用层,无效,3次握手
  6. 少一次ACK的RTT(round-trip time,往返时延)

为什么最后要等2个MSL(Maximum Segment Lifetime,最长报文寿命)

确保接收方收到ACK;
确保没有新的报文到发送方

常见的TCP攻击方式

半连接 & 全连接

在三次握手中,当客户端发送SYN到服务端,服务端收到以后回复ACK和SYN,状态由LISTEN变为SYN_RCVD,此时这个连接就被推入了SYN队列,也就是半连接队列。
当客户端返回ACK, 服务端接收后,三次握手完成。这个时候连接等待被具体的应用取走,在被取走之前,它会被推入另外一个 TCP 维护的队列,也就是全连接队列。

SYN flood攻击

客户端短时间内大量发送SYN:

  1. 服务端的大量返回ACK,半连接池吃紧
  2. 接受不到客户端的ACK,服务端超时重发

如何解决?

  • 服务端加大半连接池
  • SYN cookie:在接受达到SYN后不立即分配资源,根据这个SYN算出一个cookie,在ACK中返回给客户端,客户端在ACK里加上cookie,校验合法后分配资源

TCP的流量控制与拥塞控制

流量控制

TCP报文有窗口大小字段,接收方返回ACK报文时会带上窗口大小,发送方的发送窗口根据接收方的窗口大小调节发送窗口,接受窗口为0等待,并启动计时器,若计时器为0,则询问接受窗口的大小,继续为0等待,无反响重发报文

拥塞控制

慢启动,拥塞避免
拥塞窗口cwnd
默认为1,指数增长,慢启动阈值:ssthresh
1672026526096.jpg

快重传:收到3个ACK就重传报文
快恢复:将cwnd设置为ssthresh减半后的值,然后执行拥塞避免算法
1672026563335.jpg

TCP是如何保证keep-alive的?

客户端端等待超过一定时间后自动给服务端发送一个空的报文,如果对方回复了这个报文证明连接还存活着,如果对方没有报文返回且进行了多次尝试都是一样,那么就认为连接已经丢失,客户端就没必要继续保持连接了。如果没有这种机制就会有很多空闲的连接占用着系统资源。

HTTP

HTTP 是一种能够获取如 HTML 这样的网络资源的 protocol(通讯协议)。它是在 Web 上进行数据交换的基础,是一种 client-server 协议,也就是说,请求通常是由像浏览器这样的接受方发起的。一个完整的 Web 文档通常是由不同的子文档拼接而成的,像是文本、布局描述、图片、视频、脚本等等。

HTTP组件系统

HTTP 是一个 client-server 协议:请求通过一个实体被发出,实体也就是用户代理。大多数情况下,这个用户代理都是指浏览器,当然它也可能是任何东西,比如一个爬取网页生成维护搜索引擎索引的机器爬虫。

每一个发送到服务器的请求,都会被服务器处理并返回一个消息,也就是response。在这个请求与响应之间,还有许许多多的被称为 proxies 的实体,他们的作用与表现各不相同,比如有些是网关,还有些是caches等。
1672026680941.jpg

客户端:user-agent

user-agent 就是任何能够为用户发起行为的工具。这个角色通常都是由浏览器来扮演。一些例外情况,比如是工程师使用的程序,以及 Web 开发人员调试应用程序。

浏览器总是作为发起一个请求的实体,他永远不是服务器(虽然近几年已经出现一些机制能够模拟由服务器发起的请求消息了)。

要展现一个网页,浏览器首先发送一个请求来获取页面的 HTML 文档,再解析文档中的资源信息发送其他请求,获取可执行脚本或 CSS 样式来进行页面布局渲染,以及一些其它页面资源(如图片和视频等)。然后,浏览器将这些资源整合到一起,展现出一个完整的文档,也就是网页。浏览器执行的脚本可以在之后的阶段获取更多资源,并相应地更新网页。

一个网页就是一个超文本文档。也就是说,有一部分显示的文本可能是链接,启动它(通常是鼠标的点击)就可以获取一个新的网页,使得用户可以控制客户端进行网上冲浪。浏览器来负责发送 HTTP 请求,并进一步解析 HTTP 返回的消息,以向用户提供明确的响应。

Web 服务端

在上述通信过程的另一端,是由 Web Server 来服务并提供客户端所请求的文档。Server 只是虚拟意义上代表一个机器:它可以是共享负载(负载均衡)的一组服务器组成的计算机集群,也可以是一种复杂的软件,通过向其他计算机(如缓存,数据库服务器,电子商务服务器 …)发起请求来获取部分或全部资源。

Web 服务端

在浏览器和服务器之间,有许多计算机和其他设备转发了 HTTP 消息。由于 Web 栈层次结构的原因,它们大多都出现在传输层、网络层和物理层上,对于 HTTP 应用层而言就是透明的,虽然它们可能会对应用层性能有重要影响。还有一部分是表现在应用层上的,被称为代理(Proxies)。代理(Proxies)既可以表现得透明,又可以不透明(“改变请求”会通过它们)。代理主要有如下几种作用:

  • 缓存(可以是公开的也可以是私有的,像浏览器的缓存)
  • 过滤(像反病毒扫描,家长控制…)
  • 负载均衡(让多个服务器服务不同的请求)
  • 认证(对不同资源进行权限管理)
  • 日志记录(允许存储历史信息)

HTTP特点

HTTP是简单的

虽然下一代 HTTP/2 协议将 HTTP 消息封装到了帧(frames)中,HTTP 大体上还是被设计得简单易读。HTTP 报文能够被人读懂,还允许简单测试,降低了门槛,对新人很友好。

HTTP是无状态的,有会话的

HTTP 是无状态的:在同一个连接中,两个执行成功的请求之间是没有关系的。这就带来了一个问题,用户没有办法在同一个网站中进行连续的交互,比如在一个电商网站里,用户把某个商品加入到购物车,切换一个页面后再次添加了商品,这两次添加商品的请求之间没有关联,浏览器无法知道用户最终选择了哪些商品。而使用 HTTP 的头部扩展,HTTP Cookies 就可以解决这个问题。把 Cookies 添加到头部中,创建一个会话让每次请求都能共享相同的上下文信息,达成相同的状态。

注意,HTTP 本质是无状态的,使用 Cookies 可以创建有状态的会话。

HTTP结构

起始行+头部+空行+实体
请求报文:方法+path+HTTP版本号
响应报文:版本号+状态码+原因

1672026860487.jpg

HTTP方法

GET POST HEAD PUT DEDLETE
OPTIONS : 获取目标资源所支持的方式,用来跨域
TRACE:追踪响应-请求路径
CONNECT:建立隧道连接,用于代理服务器

GET/POST区别:

  1. 缓存
  2. 编码 GET url编码
  3. 安全性
  4. 幂等

URI

URI = Uniform Resource Identifier 统一资源标志符
URL = Uniform Resource Locator 统一资源定位符
URN = Uniform Resource Name 统一资源名称

URI是抽象的定义,不管用什么方法表示,只要能定位一个资源,就叫URI,本来设想的的使用两种方法定位:1,URL,用地址定位;2,URN 用名称定位。

举个例子:去村子找个具体的人(URI),如果用地址:某村多少号房子第几间房的主人 就是URL, 如果用身份证号+名字 去找就是URN了。

就目前而言,URL流行,平常见得URI 基本都是URL

状态码

1XX: 100 continue 101 http ->websocket 请求服务器切换更高的协议
2XX: 200 ok 204 只有响应头无body 206: partial content HTTP1.1 断点续传、分块下载
3XX:301 永久重定向 302 暂时重定向 304 缓存
4XX:400 bad request 通用 403 禁止访问 404 无资源 405 method not allowed
5XX: 500 服务器错误 501 不支持客户端请求 502 bad gateway 代理服务器异常 503 太多,无法响应

常见的传输格式内容

  • 传输定长、不定长数据

    • 定长:Content-length,指定HTTP报文长度
    • 不定长:Transfer-Encoding: chunked:表示分块传输,自动忽略Content-Length,建立长链接
  • 处理大文件

    • Accept-Range: none,允许服务器只发送 HTTP 消息的一部分到客户端,服务器端会返回状态码为 206 Partial Content 的响应:
  • 常见表单

    • application/x-www-form-urlencoded:数据会URL编码
    • multipart/form-data:常用,不需要编码,每个表单元素独立

HTTP 攻击

SQL

  • 通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中
  • 处理:对用户的输入进行转义

XSS:(Cross-site scripting)

  • 存储型 XSS
    注入型脚本永久存储在目标服务器上。当浏览器请求数据时,脚本从服务器上传回并执行。
  • 反射型 XSS
    当用户点击一个恶意链接,或者提交一个表单,或者进入一个恶意网站时,注入脚本进入被攻击者的网站。Web 服务器将注入脚本,比如一个错误信息,搜索结果等 返回到用户的浏览器上。由于浏览器认为这个响应来自”可信任”的服务器,所以会执行这段脚本。
  • 基于 DOM 的 XSS
    通过修改原始的客户端代码,受害者浏览器的 DOM 环境改变,导致有效载荷的执行。也就是说,页面本身并没有变化,但由于 DOM 环境被恶意修改,有客户端代码被包含进了页面,并且意外执行。
  • 处理:对用户的输入进行转义

CSRF: (Cross-site request forgery) 跨站请求伪造

攻击者诱导受害者进入第一方网站,在第三方网站中,向被攻击网站发送跨站请求。利用受害者在被攻击网站已经获取的注册凭证,绕过后台的用户验证,达到冒充用户对被攻击的网站执行某项操作的目的。

  • 一个典型的CSRF攻击有着如下的流程
    • 受害者登录a.com,并保留了登录凭证 (Cookie)
    • 攻击者引诱受害者访问了b.com。、
    • b.com 向 a.com 发送了一个请求: a.com/act=xx。浏览器会默认携带a.com的Cookie.
    • a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求
    • a.com以受害者的名义执行了act=xx。
    • 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作
      处理: cookie samesite

HTTP1.0 & HTTP1.1 & HTTP2 & HTTP3

HTTP1.0

  • 1.0规定浏览器和服务器保持短暂的连接。浏览器的每次请求都需要与服务器建立一个TCP连接,服务器处理完成后立即断开TCP连接(无连接),服务器不跟踪每个客户端也不记录过去的请求(无状态)
    • 无状态,使用cookie
    • 无法复用连接。每次发送请求的时候,都需要进行一次TCP连接,而TCP的连接释放过程又是比较费事的。这种无连接的特性会导致网络的利用率非常低。
    • 队头堵塞(head of line blocking)。由于HTTP/1.0规定下一个请求必须在前一个请求响应到达之前才能发送。假设一个请求响应一直不到达,那么下一个请求就不发送,就到导致阻塞后面的请求。
  • 支持方法:GET POST HEAD

HTTP1.1

  • 持久连接
    • 引入了持久连接,即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive(对于同一个域名,大多数浏览器允许同时建立6个持久连接)
  • 管道机制
    • 即在同一个TCP连接里面,客户端可以同时发送多个请求。
  • 分块传输编码
    • 即服务端没产生一块数据,就发送一块,采用”流模式”而取代”缓存模式”。
  • 新增请求方式
    • PUT:请求服务器存储一个资源;
    • DELETE:请求服务器删除标识的资源;
    • OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求;
    • TRACE:请求服务器回送收到的请求信息,主要用于测试或诊断;
    • CONNECT:保留将来使用
  • 缺点:
    • 虽然允许复用TCP连接,但是同一个TCP连接里面,所有的数据通信是按次序进行的。服务器只有处理完一个请求,才会接着处理下一个请求。如果前面的处理特别慢,后面就会有许多请求排队等着。这将导致“队头堵塞”
    • 避免方式:一是减少请求数,二是同时多开持久连接

HTTP2

  • 二进制协议

    • HTTP/1.1 版的头信息肯定是文本(ASCII编码),数据体可以是文本,也可以是二进制。HTTP/2 则是一个彻底的二进制协议,头信息和数据体都是二进制,并且统称为”帧”:头信息帧和数据帧。
    • 二进制协议解析起来更高效、“线上”更紧凑,更重要的是错误更少。
  • 完全多路复用

    • HTTP/2 复用TCP连接,在一个连接里,客户端和浏览器都可以同时发送多个请求或回应,而且不用按照顺序一一对应,这样就避免了”队头堵塞”。
  • 报头压缩

    • HTTP 协议是没有状态,导致每次请求都必须附上所有信息。所以,请求的很多头字段都是重复的,比如Cookie,一样的内容每次请求都必须附带,这会浪费很多带宽,也影响速度
    • 对于相同的头部,不必再通过请求发送,只需发送一次;
    • HTTP/2 对这一点做了优化,引入了头信息压缩机制;
    • 一方面,头信息使用gzip或compress压缩后再发送;
    • 另一方面,客户端和服务器同时维护一张头信息表,所有字段都会存入这个表,产生一个索引号,之后就不发送同样字段了,只需发送索引号。
  • 服务器推送

    • HTTP/2 允许服务器未经请求,主动向客户端发送资源;
    • 通过推送那些服务器任务客户端将会需要的内容到客户端的缓存中,避免往返的延迟

HTTP3

2022年6月6日,IETF QUIC和HTTP工作组成员Robin Mark在推特上宣布,历时5年,HTTP/3终于被标准化为 RFC 9114,这是HTTP超文本传输协议的第三个主要版本。

HTTP3 的主要改进在传输层上。传输层不会再有我前面提到的那些繁重的 TCP 连接了。现在,一切都会走 UDP。

顺便说一下,QUIC 的意思是“快速 UDP Internet 连接”。协议的这种更改将显著加快连接建立和数据传输的速度。然而,虽说 UDP 肯定更快、更简单,但它不具备 TCP 的可靠性和错误处理能力。

TCP 必须进行多次往返,才能以方形且稳定的方式建立连接。UDP 不会顾虑那么多,而且它确实可以快速运行,代价是稳定性下降和丢包的风险。但是,UDP 能大大减少请求中的延迟。到同一服务器的重复连接的延迟几乎为零,因为不需要往返来建立连接。

DNS

DNS:将主机名转为具体IP的服务

根域:就是一个“.”号,由Internet名字注册授权机构管理。全世界共有13台根域服务器。

顶级域:由Internet名字授权机构管理。共有3种类型的顶级域:

组织域:采用3个字符的代号,如edu、com、gov等。

地理域:采用2个字符的国家/地区代号,如cn、jp、hk等。

反向域:这是一个特殊域,名称为in-addr.arpa,用于将IP映射到域名。

二级域:注册到个人、组织或公司的名称。二级域下还可以创建子域。

主机名:就是FQDN最左边的部分。使用“hostname”命令可以显示当前主机名。

操作过程:递归查询,优先查找是否有DNS缓存

1672034187180.jpg

websocket

WebSockets 是一种先进的技术(H5开始支持)。它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API,您可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。