# 网络分层模型

# OSI 七层模型

OSI 七层模型 是国际标准化组织提出的一个网络分层模型,其大体结构以及每一层提供的功能如下图所示:

image.png

每一层都专注做一件事情,并且每一层都需要使用下一层提供的功能。比如传输层需要使用网络层提供的路由和寻址功能,这样传输层才知道把数据传输到哪里去。

OSI 的七层体系结构概念清楚,理论也很完整,但是它比较复杂而且不实用,而且有些功能在多个层中重复出现

上面这种图可能比较抽象,再来一个比较生动的图片。下面这个图片是我在国外的一个网站上看到的,非常赞!

image.png

既然 OSI 七层模型这么厉害,为什么干不过 TCP/IP 四层模型呢?OSI 七层模型虽然失败了,但是却提供了很多不错的理论基础。为了更好地去了解网络分层,OSI 七层模型还是非常有必要学习的。

最后再分享一个关于 OSI 七层模型非常不错的总结图片!

image.png

# TCP/IP 四层模型

TCP/IP 四层模型 是目前被广泛采用的一种模型,我们可以将 TCP / IP 模型看作是 OSI 七层模型的精简版本,由以下 4 层组成:

  1. 应用层
  2. 传输层
  3. 网络层
  4. 网络接口层

需要注意的是,我们并不能将 TCP/IP 四层模型 和 OSI 七层模型完全精确地匹配起来,不过可以简单将两者对应起来,如下图所示:

image.png

# 应用层(Application)

应用层位于传输层之上,提供两个终端设备上的应用程序之间信息交换的服务,它定义了信息交换的格式,消息会交给下一层的传输层来传输。 我们把应用层交互的数据单元称为报文

image.png

应用层协议定义了网络通信规则,对于不同的网络应用需要不同的应用层协议。在互联网中应用层协议很多,如支持 Web 应用的 HTTP 协议,支持电子邮件的 SMTP 协议等等。

image.png

# HTTP:超文本传输协议

超文本传输协议(HTTP,HyperText Transfer Protocol) 是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。

HTTP 使用客户端 - 服务器模型,客户端向服务器发送 HTTP Request(请求),服务器响应请求并返回 HTTP Response(响应),整个过程如下图所示。

image.png

HTTP 协议基于 TCP 协议,发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。目前使用的 HTTP 协议大部分都是 HTTP 1.1。在 1.1 的协议里面,默认是开启了 Keep-Alive 的,这样的话建立的连接就可以在多次请求中被复用了。

另外, HTTP 协议是” 无状态” 的协议,它无法记录客户端用户的状态,一般我们都是通过 Session 来记录客户端用户的状态。

详见 HTTP

# Websocket:全双工通信协议

WebSocket 是一种基于 TCP 协议全双工通信协议,即客户端和服务器可以同时发送和接收数据。

WebSocket 协议在 2008 年诞生,2011 年成为国际标准,几乎所有主流较新版本的浏览器都支持该协议。不过,WebSocket 不止能在基于浏览器的应用程序中使用,很多编程语言、框架和服务器都提供了 WebSocket 支持。

WebSocket 协议本质上是应用层的协议,用于弥补 HTTP 协议在持久通信能力上的不足。客户端和服务器仅需一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输

image.png

下面是 WebSocket 的常见应用场景:

  • 视频弹幕
  • 实时消息推送,详见 Web 实时消息推送详解这篇文章
  • 实时游戏对战
  • 多用户协同编辑
  • 社交聊天
  • ……

WebSocket 的工作过程可以分为以下几个步骤:

  1. 客户端向服务器发送一个 HTTP 请求,请求头中包含 Upgrade: websocketSec-WebSocket-Key 等字段,表示要求升级协议为 WebSocket
  2. 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket,它将回复一个 HTTP 101 状态码,响应头中包含 , Connection: UpgradeSec-WebSocket-Accept: xxx 等字段、表示成功升级到 WebSocket 协议。
  3. 客户端和服务器之间建立了一个 WebSocket 连接,可以进行双向的数据传输。数据以帧(frames)的形式进行传送,WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
  4. 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接

另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。

# SMTP:简单邮件传输(发送)协议

简单邮件传输(发送)协议(SMTP,Simple Mail Transfer Protocol) 基于 TCP 协议,是一种用于发送电子邮件的协议。

image.png

注意 ⚠️:接收邮件的协议不是 SMTP,而是 POP3/IMAP 协议。

SMTP 协议这块涉及的内容比较多,下面这两个问题比较重要:

  1. 电子邮件的发送过程
  2. 如何判断邮箱是真正存在的?
# 电子邮件的发送过程

比如我的邮箱是 “dabai@cszhinan.com”,我要向 “xiaoma@qq.com” 发送邮件,整个过程可以简单分为下面几步:

  1. 通过 SMTP 协议,我将我写好的邮件交给 163 邮箱服务器(邮局)
  2. 163 邮箱服务器发现我发送的邮箱是 qq 邮箱,然后它使用 SMTP 协议将我的邮件转发到 qq 邮箱服务器
  3. qq 邮箱服务器接收邮件之后就通知邮箱为 “xiaoma@qq.com” 的用户来收邮件,然后用户就通过 POP3/IMAP 协议将邮件取出。
# 判断邮箱是否有效

很多场景 (比如邮件营销) 下面我们需要判断我们要发送的邮箱地址是否真的存在,这个时候我们可以利用 SMTP 协议来检测:

  1. 查找邮箱域名对应的 SMTP 服务器地址
  2. 尝试与服务器建立连接
  3. 连接成功后尝试向需要验证的邮箱发送邮件
  4. 根据返回结果判定邮箱地址的真实性

推荐几个在线邮箱是否有效检测工具:

  1. https://verify-email.org/open in new window
  2. http://tool.chacuo.net/mailverifyopen in new window
  3. https://www.emailcamel.com/

# POP3/IMAP:邮件接收的协议

这两个协议没必要多做阐述,只需要了解 POP3 和 IMAP 两者都是负责接收邮件的协议即可(二者也是基于 TCP 协议)。另外,需要注意不要将这两者和 SMTP 协议搞混淆了。SMTP 协议只负责邮件的发送,真正负责接收邮件的协议是 POP3/IMAP

IMAP 协议是比 POP3 更新的协议,它在功能和性能上都更加强大。IMAP 支持邮件搜索、标记、分类、归档等高级功能,而且可以在多个设备之间同步邮件状态。几乎所有现代电子邮件客户端和服务器都支持 IMAP。

# FTP:文件传输协议

FTP 协议基于 TCP 协议,是一种用于在计算机之间传输文件的协议,可以屏蔽操作系统和文件存储方式。

FTP 是基于客户 — 服务器(C/S)模型而设计的,在客户端与 FTP 服务器之间建立两个连接。如果我们要基于 FTP 协议开发一个文件传输的软件的话,首先需要搞清楚 FTP 的原理。关于 FTP 的原理,很多书籍上已经描述的非常详细了:

FTP 的独特的优势同时也是与其它客户服务器程序最大的不同点就在于,它在两台通信的主机之间使用了两条 TCP 连接(其它客户服务器应用程序一般只有一条 TCP 连接):

  1. 控制连接:用于传送控制信息(命令和响应);
  2. 数据连接:用于数据传送;

这种将命令和数据分开传送的思想大大提高了 FTP 的效率。

image.png

注意 ⚠️:FTP 是一种不安全的协议,因为它在传输过程中不会对数据进行加密。因此,FTP 传输的文件可能会被窃听或篡改。建议在传输敏感数据时使用更安全的协议,如 SFTP(一种基于 SSH 协议的安全文件传输协议,用于在网络上安全地传输文件)。

# Telnet:远程登陆协议

Telnet 协议基于 TCP 协议用于通过一个终端登陆到其他服务器。Telnet 协议的最大缺点之一是所有数据(包括用户名和密码)均以明文形式发送,这有潜在的安全风险。这就是为什么如今很少使用 Telnet,而是使用一种称为 SSH 的非常安全的网络传输协议的主要原因。

image.png

# SSH:安全的网络传输协议

SSH(Secure Shell) 基于 TCP 协议通过加密和认证机制实现安全的访问和文件传输等业务

SSH 的经典用途是登录到远程电脑中执行命令。除此之外,SSH 也支持隧道协议、端口映射和 X11 连接。借助 SFTP 或 SCP 协议,SSH 还可以传输文件。

SSH 使用客户端 - 服务器模型,默认端口是 22。SSH 是一个守护进程,负责实时监听客户端请求,并进行处理。大多数现代操作系统都提供了 SSH。

image.png

# RTP:实时传输协议

RTP(Real-time Transport Protocol,实时传输协议) 通常基于 UDP 协议,但也支持 TCP 协议。它提供了端到端的实时传输数据的功能,但不包含资源预留存、不保证实时传输质量,这些功能由 WebRTC 实现。

RTP 协议分为两种子协议:

  • RTP(Real-time Transport Protocol,实时传输协议):传输具有实时特性的数据。
  • RTCP(RTP Control Protocol,RTP 控制协议):提供实时传输过程中的统计信息(如网络延迟、丢包率等),WebRTC 正是根据这些信息处理丢包

# DNS:域名系统

DNS(Domain Name System,域名管理系统)基于 UDP 协议用于解决域名和 IP 地址的映射问题。详见 DNS

image.png

# 传输层(Transport)

负责向两台终端设备的应用进程之间的通信提供通用的数据传输服务 。应用进程利用该服务传送应用层报文。“通用的” 是指并不针对某一个特定的网络应用,而是多种应用可以使用同一个传输层服务。

传输层常见协议:

image.png

  • TCP(Transmission Control Protocol,传输控制协议 ):提供 面向连接 的,可靠 的数据传输服务。
  • UDP(User Datagram Protocol,用户数据协议):提供 无连接 的,尽最大努力 的数据传输服务(不保证数据传输的可靠性),简单高效。

# 网络层(Network)

负责为分组交换网上的不同主机提供通信服务。 在发送数据时,网络层把传输层产生的报文段(segment)或用户数据报(UDP)封装成分组和包,进行传送。在 TCP/IP 体系结构中,由于网络层使用 IP 协议,因此分组也叫 IP 数据报,简称数据报

⚠️ 注意:不要把运输层的 “用户数据报 UDP” 和网络层的 “IP 数据报” 弄混。

网络层的还有一个任务就是选择合适的路由,使源主机运输层所传下来的分组,能通过网络层中的路由器找到目的主机。

这里强调指出,网络层中的 “网络” 二字已经不是我们通常谈到的具体网络,而是指计算机网络体系结构模型中第三层的名称。

互联网是由大量的异构(heterogeneous)网络通过路由器(router)相互连接起来的。互联网使用的网络层协议是无连接的网际协议(Internet Protocol)和许多路由选择协议,因此互联网的网络层也叫做 网际层 或 IP 层

网络层常见协议:

image.png

  • IP(Internet Protocol,网际协议):TCP/IP 协议中最重要的协议之一,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
  • ARP(Address Resolution Protocol,地址解析协议):ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题
  • ICMP(Internet Control Message Protocol,互联网控制报文协议):一种用于传输网络状态和错误消息的协议,常用于网络诊断和故障排除。例如,Ping 工具就使用了 ICMP 协议来测试网络连通性。
  • NAT(Network Address Translation,网络地址转换协议):NAT 协议的应用场景如同它的名称 ——网络地址转换,应用于内部网到外部网的地址转换过程中。具体地说,在一个小的子网(局域网,LAN)内,各主机使用的是同一个 LAN 下的 IP 地址,但在该 LAN 以外,在广域网(WAN)中,需要一个统一的 IP 地址来标识该 LAN 在整个 Internet 上的位置。
  • OSPF(Open Shortest Path First,开放式最短路径优先):一种内部网关协议(Interior Gateway Protocol,IGP),也是广泛使用的一种动态路由协议,基于链路状态算法,考虑了链路的带宽、延迟等因素来选择最佳路径。
  • RIP (Routing Information Protocol,路由信息协议):一种内部网关协议(Interior Gateway Protocol,IGP),也是一种动态路由协议,基于距离向量算法,使用固定的跳数作为度量标准,选择跳数最少的路径作为最佳路径。
  • BGP(Border Gateway Protocol,边界网关协议):一种用来在路由选择域之间交换网络层可达性信息(Network Layer Reachability Information,NLRI)的路由选择协议,具有高度的灵活性和可扩展性。

# 网络接口层(Network interface)

我们可以把网络接口层看作以下两层的合体:

  1. 数据链路层(data link layer):通常简称为链路层( 两台主机之间的数据传输,总是在一段一段的链路上传送的),其作用是将网络层交下来的 IP 数据报组装成帧(frame),在两个相邻节点间的链路上传送帧。每一帧包括数据和必要的控制信息(如同步信息,地址信息,差错控制等)。
  2. 物理层:其作用是实现相邻计算机节点之间比特流的透明传送,尽可能屏蔽掉具体传输介质和物理设备的差异

网络接口层重要功能和协议如下图所示:

image.png

# 小结

简单总结一下每一层包含的协议和核心技术:

image.png

TCP/IP 各层协议概览

应用层协议 :

  • HTTP(HyperText Transfer Protocol,超文本传输协议)
  • SMTP(Simple Mail Transfer Protocol,简单邮件发送协议)
  • POP3/IMAP(邮件接收协议)
  • FTP(File Transfer Protocol,文件传输协议)
  • Telnet(远程登陆协议)
  • SSH(Secure Shell Protocol,安全的网络传输协议)
  • RTP(Real-time Transport Protocol,实时传输协议)
  • DNS(Domain Name System,域名管理系统)
  • ……

传输层协议 :

  • TCP 协议
    • 报文段结构
    • 面向连接
    • 可靠数据传输
    • 流量控制
    • 拥塞控制
  • UDP 协议
    • 报文段结构
    • 无连接
    • RDT(可靠数据传输协议)

网络层协议 :

  • IP(Internet Protocol,网际协议)
  • ARP(Address Resolution Protocol,地址解析协议)
  • ICMP 协议(控制报文协议,用于发送控制消息)
  • NAT(Network Address Translation,网络地址转换协议)
  • OSPF(Open Shortest Path First,开放式最短路径优先)
  • RIP (Routing Information Protocol,路由信息协议)
  • BGP(Border Gateway Protocol,边界网关协议)
  • ……

网络接口层 :

  • 差错检测技术
  • 多路访问协议(信道复用技术)
  • CSMA/CD 协议
  • MAC 协议
  • 以太网技术
  • ……

# 网络分层的原因

“网络为什么要分层?”

说到分层,我们先从我们平时使用框架开发一个后台程序来说,我们往往会按照每一层做不同的事情的原则将系统分为三层(复杂的系统分层会更多):

  1. Repository(数据库操作)
  2. Service(业务操作)
  3. Controller(前后端数据交互)

复杂的系统需要分层,因为每一层都需要专注于一类事情。网络分层的原因也是一样,每一层只专注于做一类事情

好了,再来说回:“为什么网络要分层?”。我觉得主要有 3 方面的原因:

  1. 各层之间相互独立:各层之间相互独立,各层之间不需要关心其他层是如何实现的,只需要知道自己如何调用下层提供好的功能就可以了(可以简单理解为接口调用)。这个和我们对开发时系统进行分层是一个道理。
  2. 提高了整体灵活性:每一层都可以使用最适合的技术来实现,你只需要保证你提供的功能以及暴露的接口的规则没有改变就行了。这个和我们平时开发系统的时候要求的高内聚、低耦合的原则也是可以对应上的。
  3. 大问题化小:分层可以将复杂的网络问题分解为许多比较小的、界线比较清晰简单的小问题来处理和解决。这样使得复杂的计算机网络系统变得易于设计,实现和标准化。 这个和我们平时开发的时候,一般会将系统功能分解,然后将复杂的问题分解为容易理解的更小的问题是相对应的,这些较小的问题具有更好的边界(目标和接口)定义

我想到了计算机世界非常非常有名的一句话,这里分享一下:

计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,计算机整个体系从上到下都是按照严格的层次结构设计的。

# HTTP

# HTTP 是什么

关于 HTTP 的简介见 HTTP:超文本传输协议

# HTTP 状态码

HTTP 状态码用于描述 HTTP 请求的结果,常见的如下:

image.png

# 1xx Informational(信息性状态码)

相比于其他类别状态码来说,1xx 平时大概率不会碰到,所以这里直接跳过。

# 2xx Success(成功状态码)

  • 200 OK:请求被成功处理。比如我们发送一个查询用户数据的 HTTP 请求到服务端,服务端正确返回了用户数据。这个是我们平时最常见的一个 HTTP 状态码。
  • 201 Created:请求被成功处理并且在服务端创建了一个新的资源。比如我们通过 POST 请求创建一个新的用户。
  • 202 Accepted:服务端已经接收到了请求,但是还未处理。
  • 204 No Content:服务端已经成功处理了请求,但是没有返回任何内容。

这里格外提一下 204 状态码,平时学习 / 工作中见到的次数并不多。简单来说,204 状态码描述的是我们向服务端发送 HTTP 请求之后,只关注处理结果是否成功的场景。也就是说我们需要的就是一个结果:true/false。

举个例子:你要追一个女孩子,你问女孩子:“我能追你吗?”,女孩子回答:“好!”。我们把这个女孩子当做是服务端就很好理解 204 状态码了。

# 3xx Redirection(重定向状态码)

  • 301 Moved Permanently:资源被永久重定向了。比如你的网站的网址更换了。
  • 302 Found:资源被临时重定向了。比如你的网站的某些资源被暂时转移到另外一个网址。

# 4xx Client Error(客户端错误状态码)

  • 400 Bad Request:发送的 HTTP 请求存在问题。比如请求参数不合法、请求方法错误。
  • 401 Unauthorized:未认证却请求需要认证之后才能访问的资源。
  • 403 Forbidden:直接拒绝 HTTP 请求,不处理。一般用来针对非法请求。
  • 404 Not Found:你请求的资源未在服务端找到。比如你请求某个用户的信息,服务端并没有找到指定的用户。
  • 409 Conflict:表示请求的资源与服务端当前的状态存在冲突,请求无法被处理。

# 5xx Server Error(服务端错误状态码)

  • 500 Internal Server Error:服务端出问题了(通常是服务端出 Bug 了)。比如你服务端处理请求的时候突然抛出异常,但是异常并未在服务端被正确处理。
  • 502 Bad Gateway:我们的网关将请求转发到服务端,但是服务端返回的却是一个错误的响应。

# HTTP Header

请求头字段名说明示例
Accept能够接受的响应内容类型(Content-Types)Accept: text/plain
Accept-Charset能够接受的字符集Accept-Charset: utf-8
Accept-Datetime能够接受的按照时间来表示的版本Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT
Accept-Encoding能够接受的编码方式列表。参考 HTTP 压缩Accept-Encoding: gzip, deflate
Accept-Language能够接受的回应内容的自然语言列表。Accept-Language: en-US
Authorization用于超文本传输协议的认证的认证信息Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control用来指定在这次的请求 / 响应链中的所有缓存机制 都必须 遵守的指令Cache-Control: no-cache
Connection该浏览器想要优先使用的连接类型Connection: keep-alive Connection: Upgrade
Content-Length以 八位字节数组 (8 位的字节)表示的请求体的长度Content-Length: 348
Content-MD5请求体的内容的二进制 MD5 散列值,以 Base64 编码的结果Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Type请求体的 多媒体类型 (用于 POST 和 PUT 请求中)Content-Type: application/x-www-form-urlencoded
Cookie之前由服务器通过 Set- Cookie (下文详述)发送的一个 超文本传输协议 CookieCookie: $Version=1; Skin=new;
Date发送该消息的日期和时间 (按照 RFC 7231 中定义的 "超文本传输协议日期" 格式来发送)Date: Tue, 15 Nov 1994 08:12:31 GMT
Expect表明客户端要求服务器做出特定的行为Expect: 100-continue
From发起此请求的用户的邮件地址From: user@example.com
Host服务器的域名 (用于虚拟主机),以及服务器所监听的传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则端口号可被省略。Host: en.wikipedia.org:80open in new window
If-Match仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要作用时,用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源。If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified )If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
If-None-Match允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified )If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range如果该实体未被修改过,则向我发送我所缺少的那一个或多个部分;否则,发送整个新的实体If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since仅当该实体自某个特定时间已来未被修改的情况下,才发送回应。If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT
Max-Forwards限制该消息可被代理及网关转发的次数。Max-Forwards: 10
Origin发起一个针对 跨来源资源共享 的请求。Origin: http://www.example-social-network.comopen in new window
Pragma与具体的实现相关,这些字段可能在请求 / 回应链中的任何时候产生多种效果。Pragma: no-cache
Proxy-Authorization用来向代理进行认证的认证信息。Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range仅请求某个实体的一部分。字节偏移以 0 开始。参见字节服务。Range: bytes=500-999
Referer表示浏览器所访问的前一个页面,正是那个页面上的某个链接将浏览器带到了当前所请求的这个页面。Referer: http://en.wikipedia.org/wiki/Main_Pageopen in new window
TE浏览器预期接受的传输编码方式:可使用回应协议头 Transfer-Encoding 字段中的值;TE: trailers, deflate
Upgrade要求服务器升级到另一个协议。Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent浏览器的浏览器身份标识字符串User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0
Via向服务器告知,这个请求是由哪些代理发出的。Via: 1.0 fred, 1.1 example.comopen in new window

(Apache/1.1)
Warning一个一般性的警告,告知,在实体内容体中可能存在错误。Warning: 199 Miscellaneous warning

# ☆HTTP 和 HTTPS 的区别

# 总结

image.png

  • 端口号:HTTP 默认是 80,HTTPS 默认是 443。
  • URL 前缀:HTTP 的 URL 前缀是 http:// ,HTTPS 的 URL 前缀是 https://
  • 安全性、资源消耗
    • HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。
    • HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上,所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。
    • 所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源
  • SEO(搜索引擎优化):搜索引擎通常会更青睐使用 HTTPS 协议的网站,因为 HTTPS 能够提供更高的安全性和用户隐私保护。使用 HTTPS 协议的网站在搜索结果中可能会被优先显示,从而对 SEO 产生影响。

# HTTP 协议介绍

HTTP:超文本传输协议

# HTTP 协议通信过程

HTTP 是应用层协议,它以 TCP(传输层)作为底层协议,默认端口为 80,通信过程主要如下:

  1. 服务器监听 80 端口,等待客户的请求。
  2. 浏览器发起到服务器的 TCP 连接(创建套接字 Socket)。
  3. 服务器接收来自浏览器的 TCP 连接。
  4. 浏览器(HTTP 客户端)与 Web 服务器(HTTP 服务器)交换 HTTP 消息
  5. 关闭 TCP 连接

# HTTP 协议优点

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

# HTTPS 协议介绍

HTTPS 协议(Hyper Text Transfer Protocol Secure),是 HTTP 的加强安全版本。HTTPS 是基于 HTTP 的,也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证。默认端口号是 443

HTTPS 协议中,SSL 通道通常使用基于密钥的加密算法,密钥长度通常是 40 比特或 128 比特。

# HTTPS 协议优点

保密性好、信任度高。

# ☆HTTPS 的核心 ——SSL/TLS 协议

HTTPS 之所以能达到较高的安全性要求,就是结合了 SSL/TLS 和 TCP 协议,对通信数据进行加密,解决了 HTTP 数据透明的问题。接下来重点介绍一下 SSL/TLS 的工作原理。

# SSL 和 TLS 的区别

SSL 和 TLS 没有太大的区别。

  • SSL(Secure Sockets Layer,安全套接字)协议 ,首次发布与 1996 年。SSL 的首次发布其实已经是他的 3.0 版本,SSL 1.0 从未面世,SSL 2.0 则具有较大的缺陷(DROWN 缺陷 ——Decrypting RSA with Obsolete and Weakened eNcryption)。
  • 很快,在 1999 年,SSL 3.0 进一步升级,新版本被命名为 TLS 1.0 。因此,TLS 是基于 SSL 之上的,但由于习惯叫法,通常把 HTTPS 中的核心加密协议混称为 SSL/TLS。

# ☆SSL/TLS 工作原理

HTTPS 中的 SSL/TLS 协议采用的是混合加密方案,结合了对称加密和非对称加密技术来确保数据传输的安全性。

# 非对称加密

但是,SSL/TLS 协议实际采用的是对称加密。

SSL/TLS 的核心要素是非对称加密。非对称加密采用两个密钥 ——一个公钥,一个私钥。在通信时,私钥仅由解密者保存,公钥由任何一个想与解密者通信的发送者(加密者)所知

可以设想一个场景,在某个自助邮局,每个通信信道都是一个邮箱,每一个邮箱所有者都在旁边立了一个牌子,上面挂着一把钥匙:这是我的公钥,发送者请将信件放入我的邮箱,并用公钥锁好。但是公钥只能加锁,并不能解锁。解锁只能由邮箱的所有者 —— 因为只有他保存着私钥。

这样,通信信息就不会被其他人截获了,这依赖于私钥的保密性。

image.png

非对称加密的公钥和私钥需要采用一种复杂的数学机制生成(密码学认为,为了较高的安全性,尽量不要自己创造加密方案)。公私钥对的生成算法依赖于单向陷门函数

单向函数:已知单向函数 f,给定任意一个输入 x,易计算输出 y=f (x);而给定一个输出 y,假设存在 f (x)=y,很难根据 f 来计算出 x。

单向陷门函数:一个较弱的单向函数。已知单向陷门函数 f,陷门 h,给定任意一个输入 x,易计算出输出 y=f (x;h);而给定一个输出 y,假设存在 f (x;h)=y,很难根据 f 来计算出 x,但可以根据 f 和 h 来推导出 x。

image.png
上图就是一个单向函数(不是单项陷门函数),假设有一个绝世秘籍,任何知道了这个秘籍的人都可以把苹果汁榨成苹果,那么这个秘籍就是 “陷门” 了吧。

在这里,函数 f 相当于公钥,陷门 h 相当于私钥,输入 x 相当于原始通信数据,输出 y 相当于加密后的密文。正向计算相当于加密,逆向计算相当于解密。公钥 f 是公开的,任何人对已有输入 x,都可以用 f 加密,而要想根据加密信息还原出原信息,必须要有私钥 h 才行。

# 对称加密

使用 SSL/TLS 进行通信的双方需要使用非对称加密方案来通信,但是非对称加密设计了较为复杂的数学算法,在实际通信过程中,计算的代价较高,效率太低,因此,SSL/TLS 实际对通信数据的加密使用的是对称加密

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

image.png

对称加密的密钥生成代价比公私钥对的生成代价低得多,那么有的人会问了,为什么 SSL/TLS 还需要使用非对称加密呢?因为对称加密的保密性完全依赖于密钥的保密性。在双方通信之前,需要商量一个用于对称加密的密钥。我们知道网络通信的信道是不安全的,传输报文对任何人是可见的,密钥的交换肯定不能直接在网络信道中传输。因此,使用一次非对称加密,对对称加密的密钥进行加密,保护该密钥不在网络信道中被窃听。这样,通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性

# 公钥传输的信赖性

SSL/TLS 介绍到这里,了解信息安全的朋友又会想到一个安全隐患。

设想一个下面的场景:

客户端 C 和服务器 S 想要使用 SSL/TLS 通信,由上述 SSL/TLS 通信原理,C 需要先知道 S 的公钥,而 S 公钥的唯一获取途径,就是把 S 公钥在网络信道中传输。要注意网络信道通信中有几个前提:

  1. 任何人都可以捕获通信包
  2. 通信包的保密性由发送者设计
  3. 保密算法设计方案默认为公开,而(解密)密钥默认是安全的

因此,假设 S 公钥不做加密,在信道中传输,那么很有可能存在一个攻击者 A,发送给 C 一个诈包,假装是 S 公钥,其实是诱饵服务器 AS 的公钥。当 C 收获了 AS 的公钥(却以为是 S 的公钥),C 后续就会使用 AS 公钥对数据进行加密,并在公开信道传输,那么 A 将捕获这些加密包,用 AS 的私钥解密,就截获了 C 本要给 S 发送的内容,而 C 和 S 二人全然不知。

同样的,S 公钥即使做加密,也难以避免这种信任性问题,C 被 AS 拐跑了!

image.png

为了公钥传输的信赖性问题,第三方机构应运而生 —— 证书颁发机构(CA,Certificate Authority)。CA 默认是受信任的第三方。CA 会给各个服务器颁发证书,证书存储在服务器上,并附有 CA 的电子签名(见下节)。

当客户端(浏览器)向服务器发送 HTTPS 请求时,一定要先获取目标服务器的证书,并根据证书上的信息,检验证书的合法性。一旦客户端检测到证书非法,就会发生错误。客户端获取了服务器的证书后,由于证书的信任性是由第三方信赖机构认证的,而证书上又包含着服务器的公钥信息,客户端就可以放心的信任证书上的公钥就是目标服务器的公钥

# 数字签名

好,到这一小节,已经是 SSL/TLS 的尾声了。上一小节提到了数字签名,数字签名要解决的问题,是防止证书被伪造。第三方信赖机构 CA 之所以能被信赖,就是靠数字签名技术。

数字签名,是 CA 在给服务器颁发证书时,使用散列 + 加密的组合技术,在证书上盖个章,以此来提供验伪的功能。

具体行为如下:

CA 知道服务器的公钥,对证书采用散列技术生成一个摘要。CA 使用 CA 私钥对该摘要进行加密,并附在证书下方,发送给服务器。

现在服务器将该证书发送给客户端,客户端需要验证该证书的身份。客户端找到第三方机构 CA,获知 CA 的公钥,并用 CA 公钥对证书的签名进行解密,获得了 CA 生成的摘要。

客户端对证书数据(包含服务器的公钥)做相同的散列处理,得到摘要,并将该摘要与之前从签名中解码出的摘要做对比,如果相同,则身份验证成功;否则验证失败。

image.png

总结来说,带有证书的公钥传输机制如下:

  1. 设有服务器 S,客户端 C,和第三方信赖机构 CA。
  2. S 信任 CA,CA 是知道 S 公钥的,CA 向 S 颁发证书。并附上 CA 私钥对消息摘要的加密签名。
  3. S 获得 CA 颁发的证书,将该证书传递给 C。
  4. C 获得 S 的证书,信任 CA 并知晓 CA 公钥,使用 CA 公钥对 S 证书上的签名解密,同时对消息进行散列处理,得到摘要。比较摘要,验证 S 证书的真实性。
  5. 如果 C 验证 S 证书是真实的,则信任 S 的公钥(在 S 证书中)

image.png

对于数字签名,我这里讲的比较简单,如果你没有搞清楚的话,强烈推荐你看看数字签名及数字证书原理这个视频,这是我看过最清晰的讲解。

image.png

# HTTP 1.0 和 1.1 的区别

image.png

  • 连接方式 : HTTP/1.0 为短连接,HTTP/1.1 支持长连接。HTTP 协议的长连接和短连接,实质上是 TCP 协议的长连接和短连接
  • 状态响应码 : HTTP/1.1 中新加入了大量的状态码,光是错误响应状态码就新增了 24 种。比如说, 100 (Continue) —— 在请求大资源前的预热请求, 206 (Partial Content) —— 范围请求的标识码, 409 (Conflict) —— 请求与当前资源的规定冲突, 410 (Gone) —— 资源已被永久转移,而且没有任何已知的转发地址。
  • 缓存机制:在 HTTP/1.0 中主要使用 Header 里的 If-Modified-Since,Expires 来做为缓存判断的标准,HTTP/1.1 则引入了更多的缓存控制策略,例如 Entity tag,If-Unmodified-Since, If-Match, If-None-Match 等更多可供选择的缓存头来控制缓存策略。
  • 带宽优化:HTTP/1.0 中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来了,并且不支持断点续传功能,HTTP/1.1 则在请求头引入了 range 头域,它允许只请求资源的某个部分,即返回码是 206(Partial Content),这样就方便了开发者自由的选择以便于充分利用带宽和连接
  • Host Header 处理 : HTTP/1.1 引入了 Host Header 字段,允许在同一 IP 地址上托管多个域名,从而支持虚拟主机的功能。而 HTTP/1.0 没有 Host Header 字段,无法实现虚拟主机。

关于 HTTP/1.0 和 HTTP/1.1 更详细的对比总结,可以看我写的这篇文章:HTTP/1.0 vs HTTP/1.1(应用层)

# HTTP 1.1 和 2.0 的区别

image.png

  • 多路复用(Multiplexing)HTTP/2.0 在同一连接上可以同时传输多个请求和响应,互不干扰(可以看作是 HTTP/1.1 中长链接的升级版本)。HTTP/1.1 则使用串行方式,每个请求和响应都需要独立的连接,而浏览器为了控制资源会有 6-8 个 TCP 连接都限制。这使得 HTTP/2.0 在处理多个请求时更加高效,减少了网络延迟和提高了性能。
  • 二进制帧(Binary Frames)HTTP/2.0 使用二进制帧进行数据传输,而 HTTP/1.1 则使用文本格式的报文。二进制帧更加紧凑和高效,减少了传输的数据量和带宽消耗。
  • 头部压缩(Header Compression):HTTP/1.1 支持 Body 压缩, Header 不支持压缩。HTTP/2.0 支持对 Header 压缩,使用了专门为 Header 压缩而设计的 HPACK 算法,减少了网络开销。
  • 服务器推送(Server Push)HTTP/2.0 支持服务器推送,可以在客户端请求一个资源时,将其他相关资源一并推送给客户端,从而减少了客户端的请求次数和延迟。而 HTTP/1.1 需要客户端自己发送请求来获取相关资源。

HTTP/2.0 多路复用效果图(图源: HTTP/2 For Web Developers):

image.png

可以看到,HTTP/2.0 的多路复用使得不同的请求可以共用同一个 TCP 连接,避免建立多个连接带来不必要的额外开销,而 HTTP/1.1 中的每个请求都会建立一个单独的连接

# HTTP 2.0 和 3.0 的区别

image.png

  • 传输协议:HTTP/2.0 是基于 TCP 协议实现的,HTTP/3.0 新增了 QUIC(Quick UDP Internet Connections) 协议来实现可靠的传输,提供与 TLS/SSL 相当的安全性,具有较低的连接和传输延迟。你可以将 QUIC 看作是 UDP 的升级版本,在其基础上新增了很多功能比如加密、重传等等。HTTP/3.0 之前名为 HTTP-over-QUIC,从这个名字中我们也可以发现,HTTP/3 最大的改造就是使用了 QUIC。
  • 连接建立:HTTP/2.0 需要经过经典的 TCP 三次握手过程(由于安全的 HTTPS 连接建立还需要 TLS 握手,共需要大约 3 个 RTT)。由于 QUIC 协议的特性(TLS 1.3,TLS 1.3 除了支持 1 个 RTT 的握手,还支持 0 个 RTT 的握手)连接建立仅需 0-RTT 或者 1-RTT。这意味着 QUIC 在最佳情况下不需要任何的额外往返时间就可以建立新连接
  • 队头阻塞:HTTP/2.0 多请求复用一个 TCP 连接,一旦发生丢包,就会阻塞住所有的 HTTP 请求。由于 QUIC 协议的特性,HTTP/3.0 在一定程度上解决了队头阻塞(Head-of-Line blocking, 简写:HOL blocking)问题,一个连接建立多个不同的数据流,这些数据流之间独立互不影响,某个数据流发生丢包了,其数据流不受影响(本质上是多路复用 + 轮询)。
  • 错误恢复:HTTP/3.0 具有更好的错误恢复机制,当出现丢包、延迟等网络问题时,可以更快地进行恢复和重传。而 HTTP/2.0 则需要依赖于 TCP 的错误恢复机制。
  • 安全性:HTTP/2.0 和 HTTP/3.0 在安全性上都有较高的要求,支持加密通信,但在实现上有所不同。HTTP/2.0 使用 TLS 协议进行加密,而 HTTP/3.0 基于 QUIC 协议,包含了内置的加密和身份验证机制,可以提供更强的安全性。

HTTP/1.0、HTTP/2.0 和 HTTP/3.0 的协议栈比较:

image.png

关于 HTTP/1.0 -> HTTP/3.0 更详细的演进介绍,推荐阅读 HTTP1 到 HTTP3 的工程优化

# HTTP 如何保存用户状态

HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们如何保存用户状态呢?

Session 机制的存在就是为了解决这个问题,Session 的主要作用就是作为用户标识,在服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后,就可以标识这个用户并且跟踪这个用户了。一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个 Session。

在服务端保存 Session 的方法很多,最常用的就是内存数据库(比如是使用内存数据库 redis 保存)。既然 Session 存放在服务器端,那么我们如何实现 Session 跟踪呢?大部分情况下,我们都是通过在 Cookie 中附加一个 Session ID 来方式来跟踪。

Cookie 被禁用怎么办?最常用的就是利用 URL 重写把 Session ID 直接附加在 URL 路径的后面。

Cookie 和 Session 对比:

  • Cookie 是存储在客户端(浏览器)上的小型文本文件。它包含了一些信息,比如你的登录状态、偏好设置等,这些信息可以被发送回服务器,以便服务器识别你。
  • Session服务器端用来存储用户状态信息的一种机制。当用户登录网站时,服务器会创建一个 session,并生成一个唯一的 session ID。这个 session ID 会通过 cookie 发送给用户的浏览器,浏览器在每次请求时都会发送这个 session ID 给服务器。这样,服务器就可以通过 session ID 找到对应的 session,并获取用户的登录状态和其它信息。

简而言之,cookie 是客户端(用户浏览器)用来存储 session 信息的一种方式,而 session 是服务器用来跟踪用户状态的一种机制。cookie 通常存储 session ID,而 session 存储了用户的详细信息。两者一起工作,使得用户在浏览网站时能够有一个连续的体验。

# URI 和 URL 的区别

  • URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。
  • URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。

URI 的作用像身份证号一样,URL 的作用更像家庭住址一样。URL 是一种具体的 URI,它不仅唯一标识资源,而且还提供了定位该资源的信息

# GET 和 POST 的区别

这个问题在知乎上被讨论的挺火热的,地址:https://www.zhihu.com/question/28586791

image.png

GET 和 POST 是 HTTP 协议中两种常用的请求方法,它们在不同的场景和目的下有不同的特点和用法。一般来说,可以从以下几个方面来区分二者(重点搞清两者在语义上的区别即可):

  • 语义(主要区别)
    • **GET 通常用于获取或查询资源
    • POST 通常用于创建或修改资源
  • 幂等
    • GET 请求是幂等的,即多次重复执行不会改变资源的状态
    • POST 请求是不幂等的,即每次执行可能会产生不同的结果或影响资源的状态。
  • 格式
    • GET 请求的参数通常放在 URL 中,形成查询字符串(querystring),此外,GET 请求的 URL 长度受到浏览器和服务器的限制
    • POST 请求的参数通常放在请求体(body)中,可以有多种编码格式,如 application/x-www-form-urlencoded、multipart/form-data、application/json 等。 POST 请求的 body 大小则没有明确的限制
  • 缓存
    • 由于 GET 请求是幂等的,它可以被浏览器或其他中间节点(如代理、网关)缓存起来,以提高性能和效率。
    • POST 请求则不适合被缓存,因为它可能有副作用,每次执行可能需要实时的响应
  • 安全性
    • GET 请求和 POST 请求如果使用 HTTP 协议的话,那都不安全,因为 HTTP 协议本身是明文传输的,二者都必须使用 HTTPS 协议来加密传输数据
    • 另外,GET 请求相比 POST 请求更容易泄露敏感数据,因为 GET 请求的参数通常放在 URL 中

再次提示,重点搞清两者在语义上的区别即可,实际使用过程中,也是通过语义来区分使用 GET 还是 POST。不过,也有一些项目所有的请求都用 POST,这个并不是固定的,项目组达成共识即可。

# WebSocket

# WebSocket 是什么

关于 WebSocket 的简介见 Websocket:全双工通信协议

# WebSocket 和 HTTP 的区别

WebSocket 和 HTTP 两者都是基于 TCP 的应用层协议,都可以在网络中传输数据

下面是二者的主要区别:

  • 全双工通信:WebSocket 是一种双向实时通信协议,而 HTTP 是一种单向通信协议,只能由客户端发起,服务器无法主动通知客户端。
  • 协议前缀:WebSocket 使用 ws:// 或 wss://(使用 SSL/TLS 加密后的协议,类似于 HTTP 和 HTTPS 的关系) 作为协议前缀,HTTP 使用 http:// 或 https:// 作为协议前缀。
  • 支持拓展:WebSocket 可以支持扩展,用户可以扩展协议,实现部分自定义的子协议,如支持压缩、加密等。
  • 数据轻量WebSocket 通信数据格式比较轻量,用于协议控制的数据包头部相对较小,网络开销小。而 HTTP 通信每次都要携带完整的头部,网络开销较大(HTTP/2.0 使用二进制帧进行数据传输,还支持头部压缩,减少了网络开销)。

# WebSocket 工作过程

WebSocket 的工作过程可以分为以下几个步骤:

  1. 客户端向服务器发送一个 HTTP 请求,请求头中包含 Upgrade: websocketSec-WebSocket-Key 等字段,表示要求升级协议为 WebSocket
  2. 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket,它将回复一个 HTTP 101 状态码,响应头中包含 , Connection: UpgradeSec-WebSocket-Accept: xxx 等字段、表示成功升级到 WebSocket 协议。
  3. 客户端和服务器之间建立了一个 WebSocket 连接,可以进行双向的数据传输。数据以帧(frames)的形式进行传送,WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
  4. 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接

另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。

# WebSocket 和 SSE 的区别

摘自 Web 实时消息推送详解

SSE 与 WebSocket 作用相似,二者都可以建立服务端与浏览器之间的通信,实现服务端向客户端推送消息,但还是有些许不同:

  • SSE 是基于 HTTP 协议的,它们不需要特殊的协议或服务器实现即可工作;WebSocket 需单独服务器来处理协议。
  • SSE 单向通信,只能由服务端向客户端单向通信;WebSocket 全双工通信,即通信的双方可以同时发送和接受信息。
  • SSE 实现简单开发成本低,无需引入其他组件;WebSocket 传输数据需做二次解析,开发门槛高一些。
  • SSE 默认支持断线重连;WebSocket 则需要自己实现。
  • SSE 只能传送文本消息,二进制数据需要经过编码后传送;WebSocket 默认支持传送二进制数据。

SSE 与 WebSocket 该如何选择?

SSE 好像一直不被大家所熟知,一部分原因是出现了 WebSocket,这个提供了更丰富的协议来执行双向、全双工通信。对于游戏、即时通信以及需要双向近乎实时更新的场景,拥有双向通道更具吸引力。

但是,在某些情况下,不需要从客户端发送数据,而是只需要一些服务器操作的更新。比如:站内信、未读消息数、状态更新、股票行情、监控数量等场景,SEE 不管是从实现的难易和成本上都更加有优势。此外,SSE 具有 WebSocket 在设计上缺乏的多种功能,例如:自动重新连接、事件 ID 和发送任意事件的能力。

# PING

# PING 命令的作用

PING 命令是一种常用的网络诊断工具,经常用来测试网络中主机之间的连通性和网络延迟

这里简单举一个例子,我们来 PING 一下百度。

# 发送4个PING请求数据包到 www.baidu.com
❯ ping -c 4 www.baidu.com

PING www.a.shifen.com (14.119.104.189): 56 data bytes
64 bytes from 14.119.104.189: icmp_seq=0 ttl=54 time=27.867 ms
64 bytes from 14.119.104.189: icmp_seq=1 ttl=54 time=28.732 ms
64 bytes from 14.119.104.189: icmp_seq=2 ttl=54 time=27.571 ms
64 bytes from 14.119.104.189: icmp_seq=3 ttl=54 time=27.581 ms

--- www.a.shifen.com ping statistics ---
4 packets transmitted, 4 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 27.571/27.938/28.732/0.474 ms

PING 命令的输出结果通常包括以下几部分信息:

  1. 目标主机的域名或 IP 地址:输出结果的第一行。
  2. ICMP Echo Request(请求报文)信息:序列号、TTL(Time to Live)值。
  3. 往返时间(RTT,Round-Trip Time):从发送 ICMP Echo Request(请求报文)到接收到 ICMP Echo Reply(响应报文)的总时间,用来衡量网络连接的延迟。
  4. 统计结果(Statistics):包括发送的 ICMP 请求数据包数量、接收到的 ICMP 响应数据包数量、丢包率、往返时间(RTT)的最小、平均、最大和标准偏差值。

如果 PING 对应的目标主机无法得到正确的响应,则表明这两个主机之间的连通性存在问题(有些主机或网络管理员可能禁用了对 ICMP 请求的回复,这样也会导致无法得到正确的响应)。如果往返时间(RTT)过高,则表明网络延迟过高。

# PING 命令的工作原理

PING 基于网络层的 ICMP(Internet Control Message Protocol,互联网控制报文协议),其主要原理就是通过在网络上发送和接收 ICMP 报文实现的

ICMP 报文中包含了类型字段,用于标识 ICMP 报文类型。ICMP 报文的类型有很多种,但大致可以分为两类:

  • 查询报文类型:向目标主机发送请求并期望得到响应。
  • 差错报文类型:向源主机发送错误信息,用于报告网络中的错误情况。

PING 用到的 ICMP Echo Request(类型为 8 ) 和 ICMP Echo Reply(类型为 0) 属于查询报文类型 。

  • PING 命令会向目标主机发送 ICMP Echo Request。
  • 如果两个主机的连通性正常,目标主机会返回一个对应的 ICMP Echo Reply。

# DNS

# DNS 作用

DNS(Domain Name System) 域名系统,是当用户使用浏览器访问网址之后,使用的第一个重要协议。DNS 要解决的是域名和 IP 地址的映射问题

image.png

在实际使用中,有一些情况下,浏览器是可以不必动用 DNS 就可以获知域名和 IP 地址的映射的。在一台电脑上,可能存在浏览器 DNS 缓存,操作系统 DNS 缓存,路由器 DNS 缓存。如果以上缓存都查询不到,那么 DNS 就闪亮登场了。例如,浏览器在本地会维护一个 hosts 列表,一般来说浏览器要先查看要访问的域名是否在 hosts 列表中,如果有的话,直接提取对应的 IP 地址记录,就好了。如果本地 hosts 列表内没有 域名 - IP 对应记录的话,那么 DNS 就闪亮登场了。

目前 DNS 的设计采用的是分布式、层次数据库结构,DNS 是应用层协议,基于 UDP 协议之上,端口为 53

# DNS 服务器

DNS 服务器自底向上可以依次分为以下四个层级(所有 DNS 服务器都属于以下四个类别之一),面对一个 DNS 请求时进行依次查询:

  • 本地 DNS 服务器。每个 ISP(互联网服务提供商)都有一个自己的本地 DNS 服务器。当主机发出 DNS 请求时,该请求被发往本地 DNS 服务器,它起着代理的作用,并将该请求转发到 DNS 层次结构中。严格说来,不属于 DNS 层级结构。
  • 根 DNS 服务器。根 DNS 服务器提供 TLD 服务器的 IP 地址。目前世界上只有 13 组根服务器,我国境内目前仍没有根服务器。
  • 顶级域 DNS 服务器(TLD 服务器)。顶级域是指域名的后缀,如 comorgnetedu 等。国家也有自己的顶级域,如 ukfrca 。TLD 服务器提供了权威 DNS 服务器的 IP 地址
  • 权威 DNS 服务器。在因特网上具有公共可访问主机的每个组织机构必须提供公共可访问的 DNS 记录,这些记录将这些主机的名字映射为 IP 地址。

世界上并不是只有 13 台根服务器,这是很多人普遍的误解,网上很多文章也是这么写的。实际上,现在根服务器数量远远超过这个数量。最初确实是为 DNS 根服务器分配了 13 个 IP 地址,每个 IP 地址对应一个不同的根 DNS 服务器。然而,由于互联网的快速发展和增长,这个原始的架构变得不太适应当前的需求。为了提高 DNS 的可靠性、安全性和性能,目前 DNS 根服务器的这 13 个 IP 地址中的每一个,都有多个服务器,截止到 2023 年底,所有根服务器之和达到了 600 多台,未来还会继续增加。

# DNS 解析过程

DNS 的查询解析过程分为两种模式:

  • 迭代
  • 递归

# DNS 迭代解析过程

以下图为例,介绍 DNS 的查询解析过程。从请求主机到本地 DNS 服务器的查询是递归的,其余的查询时迭代的

image.png

该过程如下,主机 cis.poly.edu 想知道 gaia.cs.umass.edu 的 IP 地址。假设主机 cis.poly.edu 的本地 DNS 服务器为 dns.poly.edu ,并且 gaia.cs.umass.edu 的权威 DNS 服务器为 dns.cs.umass.edu

  1. 首先,主机 cis.poly.edu本地 DNS 服务器 dns.poly.edu 发送一个 DNS 请求,该查询报文包含被转换的域名 gaia.cs.umass.edu
  2. 本地 DNS 服务器 dns.poly.edu 检查本机缓存,发现并无记录,也不知道 gaia.cs.umass.edu 的 IP 地址该在何处,不得不向根 DNS 服务器发送请求。
  3. 根 DNS 服务器注意到请求报文中含有 edu 顶级域,因此告诉本地 DNS,你可以向 eduTLD DNS 服务器发送请求,因为目标域名的 IP 地址很可能在那里。
  4. 本地 DNS 获取到了 edu 的 TLD DNS 服务器地址,向其发送请求,询问 gaia.cs.umass.edu 的 IP 地址。
  5. edu 的 TLD DNS 服务器仍不清楚请求域名的 IP 地址,但是它注意到该域名有 umass.edu 前缀,因此返回告知本地 DNS, umass.edu权威 DNS 服务器可能记录了目标域名的 IP 地址。
  6. 这一次,本地 DNS 服务器将请求发送给权威 DNS 服务器 dns.cs.umass.edu
  7. 终于,由于 gaia.cs.umass.edu 向权威 DNS 服务器备案过,在这里有它的 IP 地址记录,权威 DNS 成功地将 IP 地址返回给本地 DNS。
  8. 最后,本地 DNS 获取到了目标域名的 IP 地址,将其返回给请求主机。

# DNS 递归解析过程

除了迭代式查询,还有一种递归式查询如下图,具体过程和上述类似,只是顺序有所不同。

image.png


另外,DNS 的缓存位于本地 DNS 服务器。由于全世界的根 DNS 服务器甚少,只有 600 多台,分为 13 组,且顶级域的数量也在一个可数的范围内,因此本地 DNS 通常已经缓存了很多 TLD DNS 服务器,所以在实际查找过程中,无需访问根服务器。根 DNS 服务器通常是被跳过的,不请求的。这样可以提高 DNS 查询的效率和速度,减少对根 DNS 服务器和 TLD 服务器的负担。

# DNS 报文格式

DNS 的报文格式如下图所示:

image.png

DNS 报文分为查询报文回答报文,两种形式的报文结构相同。

  • 标识符。16 比特,用于标识该查询。这个标识符会被复制到对查询的回答报文中,以便让客户用它来匹配发送的请求和接收到回答。
  • 标志。1 比特的” 查询 / 回答 “标识位0 表示查询报文, 1 表示回答报文;1 比特的” 权威的 “标志位(当某 DNS 服务器是所请求名字的权威 DNS 服务器时,且是回答报文,使用” 权威的 “标志);1 比特的” 希望递归 “标志位,显式地要求执行递归查询;1 比特的” 递归可用 “标志位,用于回答报文中,表示 DNS 服务器支持递归查询。
  • 问题数、回答 RR 数、权威 RR 数、附加 RR 数。分别指示了后面 4 类数据区域出现的数量
  • 问题区域。包含正在被查询的主机名字,以及正被询问的问题类型。
  • 回答区域。包含了对最初请求的名字的资源记录。在回答报文的回答区域中可以包含多条 RR,因此一个主机名能够有多个 IP 地址
  • 权威区域。包含了其他权威服务器的记录。
  • 附加区域。包含了其他有帮助的记录。

# DNS 资源记录(RR)

DNS 服务器在响应查询时,需要查询自己的数据库,数据库中的条目被称为资源记录 (Resource Record,RR) 。RR 提供了主机名到 IP 地址的映射。RR 是一个包含了 Name , Value , Type , TTL 四个字段的四元组。

image.png

TTL 是该记录还能生存的时间,它决定了资源记录应当从缓存中删除的时间。

NameValue 字段的取值取决于 Type

image.png

  • 如果 Type=A ,则 Name 是主机名信息, Value 是该主机名对应的 IP 地址。这样的 RR 记录了一条主机名到 IP 地址的映射。
  • 如果 Type=AAAA (与 A 记录非常相似),唯一的区别是 A 记录使用的是 IPv4,而 AAAA 记录使用的是 IPv6。
  • 如果 Type=CNAME (Canonical Name Record, 真实名称记录) ,则 Value 是别名为 Name 的主机对应的规范主机名。 Value 值才是规范主机名。 CNAME 记录将一个主机名映射到另一个主机名。 CNAME 记录用于为现有的 A 记录创建别名。下文有示例。
  • 如果 Type=NS ,则 Name 是个域,而 Value 是个知道如何获得该域中主机 IP 地址的权威 DNS 服务器的主机名。通常这样的 RR 是由 TLD 服务器发布的。
  • 如果 Type=MX ,则 Value 是个别名为 Name 的邮件服务器的规范主机名。既然有了 MX 记录,那么邮件服务器可以和其他服务器使用相同的别名。为了获得邮件服务器的规范主机名,需要请求 MX 记录;为了获得其他服务器的规范主机名,需要请求 CNAME 记录。

CNAME 记录是将一个主机域名映射到另一个主机域名(别名),而非 IP 地址。假设有下述 DNS zone:

NAME                    TYPE   VALUE
--------------------------------------------------
bar.example.com.        CNAME  foo.example.com.
foo.example.com.        A      192.0.2.23

当用户查询 bar.example.com 的时候,DNS Server 实际返回的是 foo.example.com 的 IP 地址。

# DNS 劫持

DNS 劫持是一种网络攻击,它通过修改 DNS 服务器的解析结果,使得用户访问的域名指向错误的 IP 地址,从而导致用户无法访问正常的网站,或者被引导到恶意的网站。DNS 劫持有时也被称为 DNS 重定向、DNS 欺骗或 DNS 污染。DNS 劫持详细介绍可以参考:黑客技术?没你想象的那么难!——DNS 劫持篇

# 参考

  • 《图解 HTTP》
  • 《计算机网络自顶向下方法》(第七版)
  • 详解 HTTP/2.0 及 HTTPS 协议:https://juejin.cn/post/7034668672262242318open in new window
  • HTTP 请求头字段大全 | HTTP Request Headers:https://www.flysnow.org/tools/table/http-request-headers/open in new window
  • HTTP1、HTTP2、HTTP3:https://juejin.cn/post/6855470356657307662open in new window
  • 如何看待 HTTP/3 ? - 车小胖的回答 - 知乎: https://www.zhihu.com/question/302412059/answer/533223530open in new window
  • DNS 服务器类型:https://www.cloudflare.com/zh-cn/learning/dns/dns-server-types/
  • DNS Message Resource Record Field Formats:http://www.tcpipguide.com/free/t_DNSMessageResourceRecordFieldFormats-2.htm
  • Understanding Different Types of Record in DNS Server:https://www.mustbegeek.com/understanding-different-types-of-record-in-dns-server/

# TCP 与 UDP

# ☆TCP 与 UDP 的区别

  1. 是否面向连接
    • TCP 提供面向连接的服务,在传送数据之前必须先建立连接,数据传送结束后要释放连接。
    • UDP 在传送数据之前不需要先建立连接。
  2. 是否可靠传输
    • TCP 提供可靠的传输服务,TCP 在传递数据之前,会有三次握手来建立连接,而且在数据传递时,有确认、窗口、重传、拥塞控制机制。通过 TCP 连接传输的数据,无差错、不丢失、不重复、按序到达
    • 远地主机在收到 UDP 报文后,不需要给出任何确认,并且不保证数据不丢失,不保证是否顺序到达。
  3. 是否有状态:这个和上面的 “是否可靠传输” 相对应。
    • TCP 传输是有状态的,这个有状态说的是 TCP 会去记录自己发送消息的状态,比如消息是否发送了、是否被接收了等等。为此 ,TCP 需要维持复杂的连接状态表
    • UDP 是无状态服务,简单来说就是不管发出去之后的事情了。
  4. 传输效率:由于使用 TCP 进行传输的时候多了连接、确认、重传等机制,所以 TCP 的传输效率要比 UDP 低很多
  5. 传输形式
    • TCP 是面向字节流的
    • UDP 是面向数据报文段的
  6. 首部开销:TCP 首部开销(20 ~ 60 字节)比 UDP 首部开销(8 字节)要大。
  7. 是否提供广播或多播服务
    • TCP 只支持点对点通信
    • UDP 支持一对一、一对多、多对一、多对多

我把上面总结的内容通过表格形式展示出来了!确定不点个赞嘛?

对比内容TCPUDP
是否面向连接
是否可靠
是否有状态
传输效率较慢较快
传输形式字节流数据报文段
首部开销20 ~ 60 bytes8 bytes
是否提供广播或多播服务

# TCP 和 UDP 选型

  • TCP 用于对传输准确性要求特别高的场景。比如文件传输、发送和接收邮件、远程登录等等。
  • UDP 一般用于实时通信。比如:语音、 视频、直播等等。这些场景对传输数据的准确性要求不是特别高,比如你看视频即使少个一两帧,实际给人的感觉区别也不大。

# HTTP 基于 TCP 还是 UDP?

HTTP 协议是基于 TCP 协议的,所以发送 HTTP 请求之前首先要建立 TCP 连接也就是要经历 3 次握手。

🐛 修正(参见 issue#1915):

HTTP/3.0 之前是基于 TCP 协议的,而 HTTP/3.0 将弃用 TCP,改用基于 UDP 的 QUIC 协议

此变化解决了 HTTP/2.0 中存在的队头阻塞问题。队头阻塞是指在 HTTP/2.0 中,多个 HTTP 请求和响应共享一个 TCP 连接,如果其中一个请求或响应因为网络拥塞或丢包而被阻塞,那么后续的请求或响应也无法发送,导致整个连接的效率降低。这是由于 HTTP/2.0 在单个 TCP 连接上使用了多路复用,受到 TCP 拥塞控制的影响,少量的丢包就可能导致整个 TCP 连接上的所有流被阻塞。

HTTP/3.0 在一定程度上解决了队头阻塞问题,一个连接建立多个不同的数据流,这些数据流之间独立互不影响,某个数据流发生丢包了,其数据流不受影响(本质上是多路复用 + 轮询)。

除了解决队头阻塞问题,HTTP/3.0 还可以减少握手过程的延迟。在 HTTP/2.0 中,如果要建立一个安全的 HTTPS 连接,需要经过 TCP 三次握手和 TLS 握手:

  1. TCP 三次握手:客户端和服务器交换 SYN 和 ACK 包,建立一个 TCP 连接。这个过程需要 1.5 个 RTT(round-trip time),即一个数据包从发送到接收的时间。
  2. TLS 握手:客户端和服务器交换密钥和证书,建立一个 TLS 加密层。这个过程需要至少 1 个 RTT(TLS 1.3)或者 2 个 RTT(TLS 1.2)。

所以,HTTP/2.0 的连接建立就至少需要 2.5 个 RTT(TLS 1.3)或者 3.5 个 RTT(TLS 1.2)。而在 HTTP/3.0 中,使用的 QUIC 协议(TLS 1.3,TLS 1.3 除了支持 1 个 RTT 的握手,还支持 0 个 RTT 的握手)连接建立仅需 0-RTT 或者 1-RTT。这意味着 QUIC 在最佳情况下不需要任何的额外往返时间就可以建立新连接。

相关证明可以参考下面这两个链接:

  • https://zh.wikipedia.org/zh/HTTP/3
  • https://datatracker.ietf.org/doc/rfc9114/

# 使用 TCP/UDP 的协议有哪些?

运行于 TCP 协议之上的协议:

  1. HTTP 协议(HTTP/3.0 之前):超文本传输协议(HTTP,HyperText Transfer Protocol) 是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。
  2. HTTPS 协议:更安全的超文本传输协议 (HTTPS,Hypertext Transfer Protocol Secure),身披 SSL 外衣的 HTTP 协议
  3. FTP 协议:文件传输协议 FTP(File Transfer Protocol)是一种用于在计算机之间传输文件的协议,可以屏蔽操作系统和文件存储方式。注意 ⚠️:FTP 是一种不安全的协议,因为它在传输过程中不会对数据进行加密。建议在传输敏感数据时使用更安全的协议,如 SFTP。
  4. SMTP 协议:简单邮件传输协议(SMTP,Simple Mail Transfer Protocol)的缩写,是一种用于发送电子邮件的协议。注意 ⚠️:SMTP 协议只负责邮件的发送,而不是接收。要从邮件服务器接收邮件,需要使用 POP3 或 IMAP 协议。
  5. POP3/IMAP 协议:两者都是负责接收电子邮件的协议。IMAP 协议是比 POP3 更新的协议,它在功能和性能上都更加强大。IMAP 支持邮件搜索、标记、分类、归档等高级功能,而且可以在多个设备之间同步邮件状态。几乎所有现代电子邮件客户端和服务器都支持 IMAP。
  6. Telnet 协议用于通过一个终端登陆到其他服务器。Telnet 协议的最大缺点之一是所有数据(包括用户名和密码)均以明文形式发送,这有潜在的安全风险。这就是为什么如今很少使用 Telnet,而是使用一种称为 SSH 的非常安全的网络传输协议的主要原因。
  7. SSH 协议 : SSH( Secure Shell)是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH 建立在可靠的传输协议 TCP 之上。
  8. ……

运行于 UDP 协议之上的协议:

  1. HTTP 协议(HTTP/3.0 ): HTTP/3.0 弃用 TCP,改用基于 UDP 的 QUIC 协议
  2. DHCP 协议:动态主机配置协议,动态配置 IP 地址
  3. DNS:域名系统(DNS,Domain Name System)将人类可读的域名转换为机器可读的 IP 地址。 我们可以将其理解为专为互联网设计的电话薄。实际上,DNS 同时支持 UDP 和 TCP 协议
  4. ……

# ☆TCP 三次握手和四次挥手

相关面试题:

  • 为什么要三次握手?为什么不是二次或者四次?
  • 第 2 次握手传回了 ACK,为什么还要传回 SYN?
  • 三次握手过程中可以携带数据吗?
  • 三次握手过程中的半连接队列和全连接队列是什么?
  • 为什么要四次挥手?
  • 为什么不能把服务器发送的 ACK 和 FIN 合并起来,变成三次挥手?
  • 如果第二次挥手时服务器的 ACK 没有送达客户端,会怎样?
  • 为什么第四次挥手客户端需要等待 2*MSL(报文段最长寿命)时间后才进入 CLOSED 状态?

# TCP 建立连接 —— 三次握手

# 三次握手过程

image.png

TCP 三次握手图解

建立一个 TCP 连接需要 “三次握手”,缺一不可:

  1. SYN(同步序列编号)发送:客户端将发送一个 SYN 标志位设置为 1,同时 序列号字段 seq 初始化为 x 的 TCP 段给服务器,表示客户端希望建立连接。然后,客户端进入 SYN_SENT 状态,等待服务端的确认;
  2. SYN+ACK(同步确认)响应:服务器接收到客户端的 SYN 段后,会发送一个带有 SYN 和 ACK 标志位都设置为 1,同时 seq 字段初始化为 y,ack 字段设置为客户端初始序列号加 1 的 TCP 段作为响应。然后,服务端进入 SYN_RCVD 状态;
  3. ACK(确认)发送:客户端接收到服务器的 SYN+ACK 段后,会发送一个带有 ACK 标志位设置为 1,同时 seq 字段设置为 x + 1,ack 字段设置为服务端初始序列号加 1 的 TCP 段作为最终响应。然后,客户端和服务端都进入 ESTABLISHED 状态,完成 TCP 三次握手。

至此,TCP 连接正式建立,客户端和服务器可以开始数据传输。

# 为什么要三次握手?

# 让双方都能确认自己与对方的收发功能正常

三次握手的目的是建立可靠的通信信道,说到通讯,简单来说就是数据的发送与接收,而三次握手的主要目的是:让双方都能确认自己与对方的收发功能均正常(通过判断对方是否收到了自己的数据原点的序列号)

Client、Server确认双方发送与接收功能正常的时机
发送功能接收功能
Client 视角看自己第二次握手第二次握手
Client 视角看 Server第二次握手第二次握手
Server 视角看自己第三次握手第一次握手
Server 视角看 Client第一次握手第三次握手
  1. 第一次握手:Client 什么都不能确认;Server 确认了对方发送正常,自己接收正常;
  2. 第二次握手:Client 确认了自己发送、接收正常,对方发送、接收正常;
  3. 第三次握手:Server 确认了自己发送,对方接收正常;

由此可见,三次握手是建立 TCP 连接的最小必要步骤,它解决了以下问题:

  • 确认双方的发送和接收能力:通过三次握手,双方都能确认对方的发送和接收通道都是开放的。
  • 防止重复连接:三次握手机制可以防止旧的连接请求被错误地接受。
  • 交换初始序列号:三次握手允许双方交换初始序列号,为数据传输提供同步。

因此,三次握手是 TCP 连接建立过程中的一个平衡点,既确保了连接的可靠性,又避免了不必要的复杂性和资源浪费。

# 为什么不是两次握手?

如果只有二次握手,那么在 TCP 连接建立过程中可能会出现一些问题:

  1. 服务端无法确认自己的发送能力,以及客户端的接收能力

    • 第一次握手时,客户端发送 SYN,服务器收到后发送 SYN-ACK 确认。但是,如果只有两次握手,服务器无法确认自己的数据发送能力,以及客户端是否能够接收数据。第三次握手确保了客户端能够接收服务器的数据。
  2. 已失效的连接请求突然激活,导致连接混乱

    • 三次握手可以防止一些旧的或重复的连接请求被错误地接受。如果使用二次握手,一个过时的连接请求可能会被错误地认为是新的,导致连接混乱
  3. 双方无法交换初始序列号,这是 TCP 可靠传输的基础

    • 三次握手允许双方交换初始序列号,这是 TCP 可靠传输的基础。如果只有两次握手,可能无法完成这一交换。
# 为什么不是四次握手?

如果增加到四次握手,可能会带来以下问题:

  1. 不必要的复杂性和延迟

    • 额外的握手会增加建立连接的时间,导致通信延迟。
  2. 资源浪费

    • 每次握手都需要消耗网络资源和处理能力。不必要的额外握手会浪费这些资源。
  3. 效率降低

    • TCP 设计的目标之一是高效地建立和维护连接。增加握手次数会降低这一效率。

# 第 2 次握手服务端传回了 ACK,为什么还要额外传回 SYN?

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

SYN 同步序列编号 (Synchronize Sequence Numbers) 是 TCP/IP 建立连接时使用的握手信号。在客户机和服务端之间建立正常的 TCP 网络连接时,客户机首先发出一个 SYN 消息,服务端使用 SYN-ACK 应答表示接收到了这个消息,最后客户机再以 ACK (Acknowledgement)消息响应。这样在客户机和服务端之间才能建立起可靠的 TCP 连接,数据才可以在客户机和服务端之间传递

# 三次握手过程中可以携带数据吗?

在 TCP 三次握手过程中,第三次握手是可以携带数据的(客户端发送完 ACK 确认包之后就进入 ESTABLISHED 状态了),这一点在 RFC 793 文档中有提到。也就是说,一旦完成了前两次握手,TCP 协议允许数据在第三次握手时开始传输。

如果第三次握手的 ACK 确认包丢失,但是客户端已经开始发送携带数据的包,那么服务端在收到这个携带数据的包时,如果该包中包含了 ACK 标记,服务端会将其视为有效的第三次握手确认。这样,连接就被认为是建立的,服务端会处理该数据包,并继续正常的数据传输流程。

# 半连接队列和全连接队列

在 TCP 三次握手过程中,Linux 内核会维护两个队列来管理连接请求:

  1. 半连接队列(也称 SYN Queue):当服务端收到客户端的 SYN 请求时,此时双方还没有完全建立连接,它会把半连接状态的连接放在半连接队列。
  2. 全连接队列(也称 Accept Queue):当服务端收到客户端对 ACK 响应时,意味着三次握手成功完成,服务端会将该连接从半连接队列移动到全连接队列。如果未收到客户端的 ACK 响应,会进行重传,重传的等待时间通常是指数增长的。如果重传次数超过系统规定的最大重传次数,系统将从半连接队列中删除该连接信息

这两个队列的存在是为了处理并发连接请求,确保服务端能够有效地管理新的连接请求。另外,新的连接请求被拒绝或忽略除了和每个队列的大小限制有关系之外,还和很多其他因素有关系,这里就不详细介绍了,整体逻辑比较复杂。

# TCP 断开连接 —— 四次挥手

# 四次挥手过程

image.png

由于 TCP 连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后,就能发送一个 FIN 来终止这个方向的连接。收到一个 FIN 只意味着这一方向上没有数据流动,一个 TCP 连接在收到一个 FIN 后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。

断开一个 TCP 连接则需要 “四次挥手”,缺一不可:

  1. FIN(结束)发送:当一方(假设为客户端)完成数据传输并准备关闭连接时,它发送一个带有 FIN 标志位设置为 1,同时 seq 字段初始化为 u 的 TCP 段给另一方(服务器),表示关闭客户端到服务端的数据传送。然后,客户端进入 FIN-WAIT-1 状态。
  2. ACK(确认)响应:服务器接收到 FIN 段后,会发送一个带有 ACK 标志位设置为 1,同时 seq 字段初始化为 v,ack 字段设置为客户端初始序列号加 1 的 TCP 段作为响应,表示确认客户端的断开请求。然后,服务端进入 CLOSE-WAIT 状态,客户端进入 FIN-WAIT-2 状态。
  3. FIN(结束)发送:此时,服务器可能还有未完成的数据传输。当服务器也准备关闭连接时,它会发送一个带有 FIN 标志位设置为 1 ,同时 seq 字段初始化为 w,ack 字段设置为客户端初始序列号加 1 的 TCP 段给客户端,请求关闭连接。然后,服务端进入 LAST-ACK 状态。
  4. ACK(确认)发送:客户端接收到服务器的 FIN 段后,会发送最后一个带有 ACK 标志位设置为 1,同时 seq 字段设置 u + 1,ack 字段设置为服务端初始序列号加 1 的 TCP 段作为响应,确认服务器的断开请求。然后,客户端进入 TIME-WAIT 状态,服务端在收到该数据包后进入 CLOSE 状态。此时,如果客户端等待 2MSL 后依然没有收到回复,就证明服务端已正常关闭,随后客户端也可以关闭连接了。

只要四次挥手没有结束,客户端和服务端就可以继续传输数据! 完成这四次挥手后,TCP 连接被正式终止。

# 为什么要四次挥手?

  • TCP 是全双工通信的,即数据可以在两个方向上独立传输。
  • 每个方向都可以独立关闭。当一方完成数据传输并发送 FIN 请求关闭连接时,另一方可能还有数据要发送。因此,需要四次挥手来确保双方都清楚连接即将关闭,并且都有机会完成剩余的数据传输

举个例子:A 和 B 打电话,通话即将结束后。

  1. 第一次挥手:A 说 “我没啥要说的了”
  2. 第二次挥手:B 回答 “我知道了”,但是 B 可能还会有要说的话,A 不能要求 B 跟着自己的节奏结束通话
  3. 第三次挥手:于是 B 可能又巴拉巴拉说了一通,最后 B 说 “我说完了”
  4. 第四次挥手:A 回答 “知道了”,这样通话才算结束。

# 为什么不能把服务端发送的 ACK 和 FIN 合并,变为三次挥手?

因为服务端收到客户端断开连接的请求时,可能还有一些数据没有发完,这时先回复 ACK,表示接收到了断开连接的请求。等到数据发完之后再发 FIN,断开服务端到客户端的数据传送。

# 如果第二次挥手时服务端的 ACK 没有送达到客户端,会怎样?

客户端没有收到 ACK 确认,会重新发送 FIN 请求

# 为什么第四次挥手后,客户端还需要等待 2*MSL(报文段的最长寿命)的时间后,才能进入 CLOSED 状态?

第四次挥手时,客户端发送给服务端的 ACK 有可能丢失,如果服务端因为某些原因而没有收到 ACK 的话,服务端就会重发 FIN。因此,如果客户端在 2*MSL 的时间内收到了 FIN,就会重新发送 ACK 并再次等待 2MSL,防止 Server 没有收到 ACK 而不断重发 FIN

MSL(Maximum Segment Lifetime,报文段的最长寿命) : 一个片段在网络中最大的存活时间,2MSL 就是一个发送和一个回复所需的最大时间。如果直到 2MSL,Client 都没有再次收到 FIN,那么 Client 推断 ACK 已经被服务端成功接收,则结束 TCP 连接

# 参考

  • 《计算机网络(第 7 版)》
  • 《图解 HTTP》
  • TCP and UDP Tutorial:https://www.9tut.com/tcp-and-udp-tutorial
  • 从一次线上问题说起,详解 TCP 半连接队列、全连接队列:https://mp.weixin.qq.com/s/YpSlU1yaowTs-pF6R43hMw

# ☆TCP 传输可靠性

# TCP 传输可靠性概览

  1. 基于数据块传输:应用数据被分割成 TCP 认为最适合发送的数据块,再传输给网络层,数据块被称为报文段或段
  2. 对失序数据包重新排序、去重:TCP 为了保证不发生丢包,就给每个包一个序列号,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据就可以实现数据包去重。
  3. 校验和 : TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化、差错。如果收到段的检验和有差错,TCP 将丢弃这个报文段,不确认收到此报文段。
  4. 重传机制:在数据包丢失或延迟的情况下,重新发送数据包,直到收到对方的确认应答(ACK)。TCP 重传机制主要有:基于计时器的重传(也就是超时重传)、快速重传(基于接收端的反馈信息来引发重传)、SACK(在快速重传的基础上,返回最近收到的报文段的序列号范围,这样客户端就知道,哪些数据包已经到达服务器了)、D-SACK(重复 SACK,在 SACK 的基础上,额外携带信息,告知发送方有哪些数据包自己重复接收了)。关于重传机制的详细介绍,可以查看详解 TCP 超时与重传机制这篇文章。
  5. 流量控制 : TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议(TCP 利用滑动窗口实现流量控制)。
  6. 拥塞控制:当网络拥塞时,减少数据的发送。TCP 在发送数据的时候,需要考虑两个因素:一是接收方的接收能力,二是网络的拥塞程度。接收方的接收能力由滑动窗口表示,表示接收方还有多少缓冲区可以用来接收数据。网络的拥塞程度由拥塞窗口表示,它是发送方根据网络状况自己维护的一个值,表示发送方认为可以在网络中传输的数据量。发送方发送数据的大小是滑动窗口和拥塞窗口的最小值,这样可以保证发送方既不会超过接收方的接收能力,也不会造成网络的过度拥塞。

# TCP 流量控制

TCP 利用滑动窗口实现流量控制,即控制发送方发送速率,保证接收方来得及接收。 接收方发送的确认报文中的滑动窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将滑动窗口字段设置为 0,则发送方不能发送数据。

为什么需要流量控制?这是因为双方在通信的时候,发送方的速率与接收方的速率是不一定相等,如果发送方的发送速率太快,会导致接收方处理不过来。如果接收方处理不过来的话,就只能把处理不过来的数据存在 接收缓冲区(Receiving Buffers) 里(失序的数据包也会被存放在缓存区里)。如果缓存区满了发送方还在狂发数据的话,接收方只能把收到的数据包丢掉。出现丢包问题的同时又疯狂浪费着珍贵的网络资源。因此,我们需要控制发送方的发送速率,让接收方与发送方处于一种动态平衡才好。

这里需要注意的是(常见误区):

  • 发送端不等同于客户端
  • 接收端不等同于服务端

TCP 为全双工(Full-Duplex, FDX)通信,双方可以进行双向通信,客户端和服务端既可能是发送端又可能是服务端。因此,客户端和服务端各有一个发送缓冲区与接收缓冲区,两端都各自维护一个发送窗口和一个接收窗口。接收窗口大小取决于应用、系统、硬件的限制(TCP 传输速率不能大于应用的数据处理速率)。通信双方的发送窗口和接收窗口的要求相同。

# TCP 发送窗口

TCP 发送窗口可以划分成四个部分:

  1. 已发送且已确认:已经发送并且确认的 TCP 段;
  2. 已发送但还未确认:已经发送但是没有确认的 TCP 段;
  3. 即将发送 / 可以发送:未发送但是接收方准备接收的 TCP 段;
  4. (滑动窗口移动前)不能发送:未发送并且接收方也并未准备接受的 TCP 段。

image.png

  • SND.WND:发送窗口大小。
  • SND.UNASend Unacknowledged 指针,指向发送窗口的第一个字节。
  • SND.NXTSend Next 指针,指向可发送窗口的第一个字节。

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

# TCP 接收窗口

TCP 接收窗口可以划分成三个部分:

  1. 已接收且已确认:已经接收并且已经确认的 TCP 段;
  2. 等待接收 / 可以接收但未确认:等待接收且允许发送方发送的 TCP 段;
  3. (滑动窗口移动前)不能接收:不可接收且不允许发送方发送的 TCP 段。

image.png

接收窗口的大小是根据接收端处理数据的速度动态调整的。 如果接收端读取数据快,接收窗口可能会扩大。 否则,它可能会缩小。

另外,这里的滑动窗口大小只是为了演示使用,实际窗口大小通常会远远大于这个值。

# TCP 拥塞控制

在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种情况就叫拥塞。拥塞控制就是为了防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。

拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机,所有的路由器,以及与降低网络传输性能有关的所有因素。相反,流量控制往往是点对点通信量的控制,是个端到端的问题。流量控制所要做到的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

TCP 拥塞控制

为了进行拥塞控制,TCP 发送方要维持一个 拥塞窗口(cwnd) 的状态变量。拥塞控制窗口的大小取决于网络的拥塞程度,并且动态变化。发送方让自己的发送窗口取值为拥塞窗口和接收方的接收窗口中的较小值

TCP 的拥塞控制采用了四种算法:

  • 慢开始: 思想是当主机开始发送数据时,如果立即把大量数据字节注入到网络,那么可能会引起网络阻塞,因为现在还不知道网络的符合情况。经验表明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口,cwnd 初始值为 1,每经过一个传播轮次,cwnd 加倍。
  • 拥塞避免: 思路是线性增大拥塞窗口,即每经过一个往返时间 RTT 就把发送方的 cwnd 加 1。
  • 快重传快恢复: 在 TCP/IP 中, 快速重传和恢复(fast retransmit and recovery,FRR) 是一种拥塞控制算法,它能快速恢复丢失的数据包。没有 FRR,如果数据包丢失了,TCP 将会使用定时器来要求暂停传输。在暂停的这段时间内,没有新的或复制的数据包被发送。
    • 有了 FRR,如果接收机接收到一个不按顺序的数据段,它会立即给发送机发送一个重复确认。如果发送机累积接收到三个重复确认,它就会假定确认中指出的数据段丢失了,并立即重传这些丢失的数据段
    • 有了 FRR,就不会因为重传时要求的暂停被耽误。 当有单独的数据包丢失时,快速重传和恢复(FRR)能最有效地工作。当有多个数据信息包在某一段很短的时间内丢失时,它则不能很有效地工作。

# ARQ 协议

自动重传请求(Automatic Repeat-reQuest,ARQ)协议是 OSI 模型中数据链路层和传输层的错误纠正协议之一。它通过使用确认超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。如果发送方在发送后一段时间之内没有收到确认信息,它通常会重新发送,直到收到确认或者重试超过一定的次数。

ARQ 包括停止等待 ARQ 协议连续 ARQ 协议,略过。

# 停止等待 ARQ 协议

停止等待协议是为了实现可靠传输的,它的基本原理就是每发完一个分组就停止发送,等待对方确认(回复 ACK)。如果过了一段时间(超时时间后),还是没有收到 ACK 确认,说明没有发送成功,需要重新发送,直到收到确认后再发下一个分组;

在停止等待协议中,若接收方收到重复分组,就丢弃该分组,但同时还要发送确认。

1) 无差错情况:

发送方发送分组,接收方在规定时间内收到,并且回复确认。发送方再次发送。

2) 出现差错情况(超时重传):

停止等待协议中超时重传是指只要超过一段时间仍然没有收到确认,就重传前面发送过的分组(认为刚才发送过的分组丢失了)。因此每发送完一个分组需要设置一个超时计时器,其重传时间应比数据在分组传输的平均往返时间更长一些。这种自动重传方式常称为 自动重传请求 ARQ 。另外在停止等待协议中若收到重复分组,就丢弃该分组,但同时还要发送确认。

3) 确认丢失和确认迟到

  • 确认丢失:确认消息在传输过程丢失。当 A 发送 M1 消息,B 收到后,B 向 A 发送了一个 M1 确认消息,但却在传输过程中丢失。而 A 并不知道,在超时计时过后,A 重传 M1 消息,B 再次收到该消息后采取以下两点措施:1. 丢弃这个重复的 M1 消息,不向上层交付。 2. 向 A 发送确认消息。(不会认为已经发送过了,就不再发送。A 能重传,就证明 B 的确认消息丢失)。
  • 确认迟到:确认消息在传输过程中迟到。A 发送 M1 消息,B 收到并发送确认。在超时时间内没有收到确认消息,A 重传 M1 消息,B 仍然收到并继续发送确认消息(B 收到了 2 份 M1)。此时 A 收到了 B 第二次发送的确认消息。接着发送其他数据。过了一会,A 收到了 B 第一次发送的对 M1 的确认消息(A 也收到了 2 份确认消息)。处理如下:1. A 收到重复的确认后,直接丢弃。2. B 收到重复的 M1 后,也直接丢弃重复的 M1。

# 连续 ARQ 协议

连续 ARQ 协议可提高信道利用率。发送方维持一个发送窗口,凡位于发送窗口内的分组可以连续发送出去,而不需要等待对方确认。接收方一般采用累计确认,对按序到达的最后一个分组发送确认,表明到这个分组为止的所有分组都已经正确收到了。

  • 优点: 信道利用率高,容易实现,即使确认丢失,也不必重传。
  • 缺点: 不能向发送方反映出接收方已经正确收到的所有分组的信息。 比如:发送方发送了 5 条 消息,中间第三条丢失(3 号),这时接收方只能对前两个发送确认。发送方无法知道后三个分组的下落,而只好把后三个全部重传一次。这也叫 Go-Back-N(回退 N),表示需要退回来重传已经发送过的 N 个消息。

# TCP 超时重传

当发送方发送数据之后,它启动一个定时器,等待接收端确认收到这个报文段。接收端实体对已成功收到的包发回一个相应的确认信息(ACK)。如果发送端在合理的往返时延(RTT)内未收到确认消息,那么对应的数据包就被假设为已丢失,并进行重传

  • RTT(Round Trip Time)往返时间,也就是数据包从发出去到收到对应 ACK 的时间。
  • RTO(Retransmission Time Out)重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传。

RTO 的确定是一个关键问题,因为它直接影响到 TCP 的性能和效率。如果 RTO 设置得太小,会导致不必要的重传,增加网络负担;如果 RTO 设置得太大,会导致数据传输的延迟,降低吞吐量。因此,RTO 应该根据网络的实际状况,动态地进行调整。

RTT 的值会随着网络的波动而变化,所以 TCP 不能直接使用 RTT 作为 RTO。为了动态地调整 RTO,TCP 协议采用了一些算法,如加权移动平均(EWMA)算法,Karn 算法,Jacobson 算法等,这些算法都是根据往返时延(RTT)的测量和变化来估计 RTO 的值

# 参考

  1. 《计算机网络(第 7 版)》
  2. 《图解 HTTP》
  3. https://www.9tut.com/tcp-and-udp-tutoria
  4. https://github.com/wolverinn/Waking-Up/blob/master/Computer%20Network.md
  5. TCP Flow Control—https://www.brianstorti.com/tcp-flow-control/
  6. TCP 流量控制 (Flow Control):https://notfalse.net/24/tcp-flow-control
  7. TCP 之滑动窗口原理 : https://cloud.tencent.com/developer/article/1857363

# IP

# IP 作用

IP(Internet Protocol,网际协议) 是 TCP/IP 协议中最重要的协议之一,属于网络层的协议,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。

目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。

# IP 地址

每个连入互联网的设备或域(如计算机、服务器、路由器等)都被分配一个 IP 地址(Internet Protocol address) ,作为唯一标识符。每个 IP 地址都是一个字符序列,如 192.168.1.1(IPv4)、2001:0db8:85a3:0000:0000:8a2e:0370:7334(IPv6) 。

当网络设备发送 IP 数据包时,数据包中包含了 源 IP 地址目的 IP 地址 。源 IP 地址用于标识数据包的发送方设备或域,而目的 IP 地址则用于标识数据包的接收方设备或域。这类似于一封邮件中同时包含了目的地地址和回邮地址。

网络设备根据目的 IP 地址来判断数据包的目的地,并将数据包转发到正确的目的地网络或子网络,从而实现了设备间的通信。

这种基于 IP 地址的寻址方式是互联网通信的基础,它允许数据包在不同的网络之间传递,从而实现了全球范围内的网络互联互通。IP 地址的唯一性和全局性保证了网络中的每个设备都可以通过其独特的 IP 地址进行标识和寻址。

image.png

IP 地址使数据包到达其目的地

# IP 地址过滤

IP 地址过滤(IP Address Filtering) 简单来说就是限制或阻止特定 IP 地址或 IP 地址范围的访问。例如,你有一个图片服务突然被某一个 IP 地址攻击,那我们就可以禁止这个 IP 地址访问图片服务。

IP 地址过滤是一种简单的网络安全措施,实际应用中一般会结合其他网络安全措施,如认证、授权、加密等一起使用。单独使用 IP 地址过滤并不能完全保证网络的安全。

# IPv4 和 IPv6 的区别

IPv4(Internet Protocol version 4) 是目前广泛使用的 IP 地址版本,其格式是四组由点分隔的数字,例如:123.89.46.72。IPv4 使用 32 位地址作为其 Internet 地址,这意味着共有约 42 亿( 2^32)个可用 IP 地址。

image.png

这么少当然不够用啦!为了解决 IP 地址耗尽的问题,最根本的办法是采用具有更大地址空间的新版本 IP 协议 - IPv6(Internet Protocol version 6) 。IPv6 地址使用更复杂的格式,该格式使用由单或双冒号分隔的一组数字和字母,例如:2001:0db8:85a3:0000:0000:8a2e:0370:7334 。IPv6 使用 128 位地址,这意味着越有 2^128(3 开头的 39 位数字,恐怖如斯) 个可用 IP 地址。

image.png

除了更大的地址空间之外,IPv6 的优势还包括:

  • 无状态地址自动配置(Stateless Address Autoconfiguration,简称 SLAAC):主机可以直接通过根据接口标识和网络前缀生成全局唯一的 IPv6 地址。即 IP 地址的生成不再依赖 DHCP(Dynamic Host Configuration Protocol)服务器,简化了网络配置和管理。
  • NAT(Network Address Translation,网络地址转换) 成为可选项:IPv6 地址资源充足,可以给全球每个设备一个独立的地址。NAT 的作用
  • 标头结构更加简洁高效:IPv6 标头结构相较于 IPv4 更加简化和高效,减少了处理开销,提高了网络性能。
  • 可选的扩展头:允许在 IPv6 标头中添加不同的扩展头(Extension Headers),用于实现不同类型的功能和选项。
  • ICMPv6(Internet Control Message Protocol for IPv6):IPv6 中的 ICMPv6 相较于 IPv4 中的 ICMP 有了一些改进,如邻居发现、路径 MTU 发现等功能的改进,从而提升了网络的可靠性和性能。
  • ……

# 如何获取客户端的真实 IP ?

获取客户端真实 IP 的方法有多种,主要分为应用层方法、传输层方法和网络层方法。

# 应用层方法

通过 X-Forwarded-For 请求头获取,简单方便。不过,这种方法无法保证获取到的是真实 IP,这是因为 X-Forwarded-For 字段可能会被伪造。如果经过多个代理服务器,X-Forwarded-For 字段可能会有多个值(附带了整个请求链中的所有代理服务器 IP 地址)。并且,这种方法只适用于 HTTP 和 SMTP 协议

# 传输层方法

利用 TCP Options 字段承载真实源 IP 信息。这种方法适用于任何基于 TCP 的协议,不受应用层的限制。不过,这并非是 TCP 标准所支持的,所以需要通信双方都进行改造。也就是:对于发送方来说,需要有能力把真实源 IP 插入到 TCP Options 里面。对于接收方来说,需要有能力把 TCP Options 里面的 IP 地址读取出来。

也可以通过 Proxy Protocol 协议来传递客户端 IP 和 Port 信息。这种方法可以利用 Nginx 或者其他支持该协议的反向代理服务器来获取真实 IP 或者在业务服务器解析真实 IP。

# 网络层方法

隧道 +DSR 模式。这种方法可以适用于任何协议,就是实施起来会比较麻烦,也存在一定限制,实际应用中一般不会使用这种方法。

# NAT 的作用

NAT(Network Address Translation,网络地址转换) 主要用于在不同网络之间转换 IP 地址。它允许将私有 IP 地址(如在局域网中使用的 IP 地址)映射为公有 IP 地址(在互联网中使用的 IP 地址)或者反向映射,从而实现局域网内的多个设备通过单一公有 IP 地址访问互联网。

NAT 不光可以缓解 IPv4 地址资源短缺的问题,还可以隐藏内部网络的实际拓扑结构,使得外部网络无法直接访问内部网络中的设备,从而提高了内部网络的安全性。

image.png

NAT 实现 IP地址转换

相关阅读:NAT 协议详解(网络层)

# ARP

# Mac 地址

MAC 地址的全称是 媒体访问控制地址(Media Access Control Address) 。如果说,互联网中每一个资源都由 IP 地址唯一标识(IP 协议内容),那么每一个网络设备都由 MAC 地址唯一标识

image.png

路由器的背面就会注明 MAC 位址

可以理解为,MAC 地址才是一个网络设备真正的身份证号,IP 地址只是一种不重复的定位方式(比如说住在某省某市某街道的张三,这种逻辑定位是 IP 地址,他的身份证号才是他的 MAC 地址),也可以理解为 MAC 地址是身份证号,IP 地址是邮政地址。MAC 地址也有一些别称,如 LAN 地址、物理地址、以太网地址等。

还有一点要知道的是,不仅仅是网络资源才有 IP 地址,网络设备也有 IP 地址,比如路由器。但从结构上说,路由器等网络设备的作用是组成一个网络,而且通常是内网,所以它们使用的 IP 地址通常是内网 IP,内网的设备在与内网以外的设备进行通信时,需要用到 NAT 协议。

MAC 地址的长度为 6 字节(48 比特),地址空间大小有 280 万亿之多(248),MAC 地址由 IEEE 统一管理与分配,理论上,一个网络设备中的网卡上的 MAC 地址是永久的。不同的网卡生产商从 IEEE 那里购买自己的 MAC 地址空间(MAC 的前 24 比特),也就是前 24 比特由 IEEE 统一管理,保证不会重复。而后 24 比特,由各家生产商自己管理,同样保证生产的两块网卡的 MAC 地址不会重复。

MAC 地址具有可携带性、永久性,身份证号永久地标识一个人的身份,不论他到哪里都不会改变。而 IP 地址不具有这些性质,当一台设备更换了网络,它的 IP 地址也就可能发生改变,也就是它在互联网中的定位发生了变化。

最后,记住,MAC 地址有一个特殊地址:FF-FF-FF-FF-FF-FF(全 1 地址),该地址表示广播地址

# ARP 协议的作用

ARP 协议,全称 地址解析协议(Address Resolution Protocol) ,它解决的是网络层地址(IP)和链路层地址(MAC)之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。

# ARP 协议的工作原理

ARP 协议详解 (网络层)

# 复习建议

非常推荐大家看一下 《图解 HTTP》 这本书,这本书页数不多,但是内容很是充实,不管是用来系统的掌握网络方面的一些知识还是说纯粹为了应付面试都有很大帮助。下面的一些文章只是参考。大二学习这门课程的时候,我们使用的教材是 《计算机网络第七版》(谢希仁编著),不推荐大家看这本教材,书非常厚而且知识偏理论,不确定大家能不能心平气和的读完。

# 参考

  • 《图解 HTTP》
  • 《计算机网络自顶向下方法》(第七版)
  • 什么是 Internet 协议(IP)?:https://www.cloudflare.com/zh-cn/learning/network-layer/internet-protocol/
  • 透传真实源 IP 的各种方法 - 极客时间:https://time.geekbang.org/column/article/497864
  • What Is NAT and What Are the Benefits of NAT Firewalls?:https://community.fs.com/blog/what-is-nat-and-what-are-the-benefits-of-nat-firewalls.html

# 重要知识点

# 在浏览器地址栏输入 URL 并按下回车键到页面展示,背后发生了什么?

类似的问题:打开一个网页,整个过程会使用哪些协议?

开发岗中总是会考很多计算机网络的知识点,但如果让面试官只靠一道题,便涵盖最多的计网知识点,那可能就是 网页浏览的全过程 了。本篇文章将带大家从头到尾过一遍这道被考烂的面试题,必会!!!

总的来说,网络通信模型可以用下图来表示,也就是大家只要熟记网络结构五层模型,按照这个体系,很多知识点都能顺出来了。访问网页的过程也是如此。

image.png

先来看《图解 HTTP》中的一张图,其中有一个错误需要注意:是 OSPF 不是 OPSF。 OSPF(Open Shortest Path First,ospf)开放最短路径优先协议,是由 Internet 工程任务组开发的路由选择协议。

image.png

开始之前,先简单过一遍完整流程:

  1. DNS 解析:浏览器首先需要将输入的域名解析为 IP 地址。这通过查询 DNS 服务器完成,DNS 服务器将域名映射到服务器的 IP 地址。
  2. 建立 TCP 连接:浏览器根据 IP 地址和端口号,向目标服务器发起一个 TCP 连接请求
  3. 发送 HTTP 请求:浏览器在 TCP 连接上,向服务器发送一个 HTTP 请求报文,请求获取网页的内容。如果是安全连接,则使用 HTTPS,该协议在 HTTP 上增加了 SSL/TLS 加密层。
  4. SSL/TLS 握手(如果使用 HTTPS):在数据传输之前,如果使用 HTTPS,浏览器和服务器会进行 SSL/TLS 握手,以建立一个加密的通信通道。
  5. 服务器处理 HTTP 请求并响应:服务器收到 HTTP 请求报文后,处理请求,并返回 HTTP 响应报文给浏览器。响应中包含了请求的网页内容,如 HTML、CSS、JavaScript 文件等。
  6. 浏览器渲染页面:浏览器收到服务器的 HTTP 响应报文后,会开始解析响应体中的 HTML 代码,并根据 HTML、CSS 和 JavaScript 文件渲染网页的结构和样式。同时,浏览器可能会加载其他资源,根据 HTML 中的其他资源的 URL(如图片、CSS、JS 等),再次发起 HTTP 请求,获取这些资源的内容,直到网页完全加载显示。
  7. TCP 连接关闭:一旦数据传输完成,浏览器就不需要和服务器通信了,可以主动关闭 TCP 连接,或者等待服务器的关闭请求。

# 应用层

一切的开始 —— 打开浏览器,在地址栏输入 URL,回车确认。那么,什么是 URL?访问 URL 有什么用?

# URL

URL(Uniform Resource Locators) ,即统一资源定位器。网络上的所有资源都靠 URL 来定位,每一个文件就对应着一个 URL,就像是路径地址。理论上,文件资源和 URL 一一对应。实际上也有例外,比如某些 URL 指向的文件已经被重定位到另一个位置,这样就有多个 URL 指向同一个文件。

# URL 的组成结构

image.png

  1. 协议。URL 的前缀通常表示了该网址采用了何种应用层协议,通常有两种 ——HTTP 和 HTTPS。当然也有一些不太常见的前缀头,比如文件传输时用到的 ftp:
  2. 域名。域名便是访问网址的通用名,这里也有可能是网址的 IP 地址,域名可以理解为 IP 地址的可读版本,毕竟绝大部分人都不会选择记住一个网址的 IP 地址。
  3. 端口。如果指明了访问网址的端口的话,端口会紧跟在域名后面,并用一个冒号隔开。
  4. 资源路径。域名(端口)后紧跟的就是资源路径,从第一个 / 开始,表示从服务器上根目录开始进行索引到的文件路径,上图中要访问的文件就是服务器根目录下 /path/to/myfile.html 。早先的设计是该文件通常物理存储于服务器主机上,但现在随着网络技术的进步,该文件不一定会物理存储在服务器主机上,有可能存放在云上,而文件路径也有可能是虚拟的(遵循某种规则)。
  5. 参数。参数是浏览器在向服务器提交请求时,在 URL 中附带的参数。服务器解析请求时,会提取这些参数。参数采用键值对的形式 key=value ,每一个键值对使用 & 隔开。参数的具体含义和请求操作的具体方法有关。
  6. 锚点。顾名思义,是在要访问的页面上的一个锚。要访问的页面大部分都多于一页,如果指定了锚点,那么在客户端显示该网页是就会定位到锚点处,相当于一个小书签。值得一提的是,在 URL 中,锚点以 # 开头,并且不会作为请求的一部分发送给服务端。

# DNS 协议

键入了 URL 之后,第一个重头戏登场 ——DNS 服务器解析。 DNS(Domain Name System) 域名系统,它要解决的是 域名和 IP 地址的映射问题 。毕竟,域名只是一个网址便于记住的名字,而网址真正存在的地址其实是 IP 地址。

传送门:DNS

# HTTP/HTTPS

利用 DNS 拿到了目标主机的 IP 地址之后,浏览器便可以向目标 IP 地址发送 HTTP 报文,请求需要的资源了。在这里,根据目标网站的不同,请求报文可能是 HTTP 协议或安全性增强的 HTTPS 协议。

传送门:

  • HTTPS 是如何保证传输安全的?
  • HTTP 常见的状态码有哪些?
  • HTTP 1.0 和 HTTP 1.1 有什么区别?

# 传输层

由于 HTTP 协议是基于 TCP 协议的,在应用层的数据封装好以后,要交给传输层,经 TCP 协议继续封装。

TCP 协议保证了数据传输的可靠性,是数据包传输的主力协议

传送门:

# 网络层

终于,来到网络层,此时我们的主机不再是和另一台主机进行交互了,而是在和中间系统进行交互。也就是说,应用层和传输层都是端到端的协议,而网络层及以下都是中间件的协议了

网络层的的核心功能 —— 转发与路由,必会!!!如果面试官问到了网络层,而你恰好又什么都不会的话,最最起码要说出这五个字。

  • 转发:将分组从路由器的输入端口转移到合适的输出端口。
  • 路由:确定分组从源到目的经过的路径。

所以到目前为止,我们的数据包经过了应用层、传输层的封装,来到了网络层,终于开始准备在物理层面传输了,第一个要解决的问题就是 —— 往哪里传输?或者说,要把数据包发到哪个路由器上? 这便是 BGP 协议要解决的问题。