走进HTTP之基础原理详解

66 阅读21分钟

网络基础

  • OSI 模型与TCP/IP标准模型
  • OSI模型 - OSI(Open System Interconnect),即开放式系统互联。
  • 应用层 - OSI参考模型中最靠近用户的一层,是为计算机用户提供应用接口,也为用户直接提供各种网络服务。我们常见应用层的网络服务协议有:HTTP,HTTPS,FTP,POP3、SMTP等。
  • 表示层 - 提供各种用于应用层数据的编码和转换功能,确保一个系统的应用层发送的数据能被另一个系统的应用层识别。
  • 会话层 - 就是负责建立、管理和终止表示层实体之间的通信会话。
  • 传输层 - 建立了主机端到端的链接,传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题。
  • 网络层 - 本层通过IP寻址来建立两个节点之间的连接,为源端的运输层送来的分组,选择合适的路由和交换节点,正确无误地按照地址传送给目的端的运输层。
  • 数据链路层 - 将比特组合成字节,再将字节组合成帧,使用链路层地址 (以太网使用MAC地址)来访问介质,并进行差错检测。
  • 物理层 - 实际最终信号的传输是通过物理层实现的,通过物理介质传输比特流。
  • TCP/IP协议模型
  • 基础协议
  • IP - 用于在网络中传输数据包,常见的IP协议版本是IPv4和IPv6。
  • 它负责将数据包从源地址传输到目的地址,并确保它们以正确的顺序到达。
  • IP协议是一种无连接协议,它将数据分成小的数据包,每个数据包都有自己的地址信息和其他控制信息,然后通过网络单独传输。
  • IP协议还负责将不同网络之间的数据包路由到正确的目的地。
  • TCP:传输层协议,用于在网络中可靠地传输数据,它确保数据以正确的顺序和无丢失地到达目的地。在网络通信中,TCP协议被广泛使用,例如Web浏览器和Web服务器之间的通信,电子邮件客户端和邮件服务器之间的通信等。
  • 建立连接:在TCP协议中,发送方和接收方使用三次握手协议来建立连接。首先,发送方发送一个SYN(同步)数据包给接收方,接收方回复一个SYN/ACK(同步/确认)数据包给发送方,最后,发送方回复一个ACK(确认)数据包给接收方。这样,发送方和接收方就可以协商一些参数,例如最大的数据包大小和流量控制。
  • 数据传输:TCP协议将数据分成小的数据段,并确保它们以正确的顺序和无丢失地到达目的地。每个数据段都有自己的序列号和确认号,用于检测和纠正数据丢失或损坏。
  • 流量控制:TCP协议使用流量控制算法来确保发送方不会淹没接收方。接收方可以告诉发送方它可以接收的数据量,发送方根据这个信息来控制发送速率。
  • 拥塞控制:TCP协议还使用拥塞控制算法来确保网络的可靠性和效率。如果网络出现拥塞,TCP协议会减少发送速率,避免网络崩溃。
  • 断开连接:在TCP协议中,发送方和接收方使用四次握手协议来关闭连接。首先,发送方发送一个FIN(结束)数据包给接收方,接收方回复一个ACK(确认)数据包给发送方,然后,接收方发送一个FIN数据包给发送方,发送方回复一个ACK数据包给接收方。这样,连接就被安全地关闭了。
  • UDP:传输层协议,无连接,不可靠的数据传输协议,不需要维护连接状态,不需要关注重传、顺序、流量控制等,因此数据传输过程中的延迟小,数据传输效率高。UDP协议常用于音频、视频、在线游戏等实时数据传输场景,因为这些场景对传输速度和低延迟要求较高,而对数据可靠性要求较低。
  • TLS:安全传输层协议,用于在网络中安全地传输数据,它可以保护数据的机密性、完整性和真实性。
  • HTTP:用于Web应用的通信协议,它是一种无状态的、应用层的协议。HTTP目前常用的还是1.x版本,2.0常用的有gRpc,3.0常用的Quic。
  • HTTPS:HTTP+TLS的组合体。
  • URI - 用于标识和定位资源的字符串
  • URI用于标识和定位资源,包括Web页面、文件、数据库记录、邮件地址等。每个URI都唯一地标识一个资源,可以用于从互联网上定位和访问该资源。
  • URL - 是URI的一个子集,它包括了一个协议名(例如HTTP、FTP等)、服务器名、端口号和路径等信息,用于标识和定位Web页面或其他资源。
  • URL = scheme ":" ["//" authority[userinfo@host:port]] path ["?" query] ["#" fragment]

基本概念

  • 关于HTTP - HTTP(HyperText Transfer Protocol)是一种用于在Web上传输数据的协议,它定义了客户端和服务器之间的通信规则。

发展历程

  • HTTP/1.0
  • HTTP正式作为标准被公布是在1996年的5月,版本被命名为HTTP/1.0,并记载于RFC1945。
  • 支持多种 MIME 类型,引入了请求头和响应头,支持POST方法和状态码,但没有持久连接,每个请求需要建立一次TCP连接。
  • RFC1945 - Hypertext Transfer Protocol -- HTTP/1.0
  • HTTP/1.1
  • 1997 年 1 月公布的 HTTP/1.1 是目前主流的 HTTP 协议版本。
  • 引入了持久连接、管道化、分块传输编码等技术,支持多种请求方法,增加了缓存控制、虚拟主机、Range头等特性。
  • RFC2616 - Hypertext Transfer Protocol -- HTTP/1.1
  • HTTP/2
  • 2015年,HTTP/2发布。
  • 通过多路复用技术,将多个请求同时发送到服务器,支持服务器推送,提高了性能和效率。
  • RFC7540 - Hypertext Transfer Protocol Version 2 (HTTP/2)
  • HTTP/3
  • 2020年,HTTP/3发布
  • 采用基于UDP的QUIC传输协议,有效地解决了TCP协议的一些问题,如传输延迟、拥塞控制等。
  • HTTP/3标准还未正式发布,目前处于草案阶段。RFC 9114 - HTTP/3

工作原理

  • 建立连接:客户端与服务器之间建立TCP连接,以便进行通信。
  • 三次握手三次握手原因:为了避免因传输异常导致包时序问题,一端在发消息时必须要接收到对方的回包确认。例如客户端因网络延迟发了两个SYN,如果没有第三次握手ACK,则服务端会二次建立连接。
  • 发送请求:客户端向服务器发送HTTP请求消息,请求消息包括请求方法、URL、协议版本、请求头和请求体等信息。
  • 处理请求:服务器接收到请求消息后,根据请求方法和URL等信息处理请求,并生成HTTP响应消息。
  • 发送响应:服务器向客户端发送HTTP响应消息,响应消息包括状态码、响应头和响应体等信息。
  • 关闭连接:客户端和服务器之间的TCP连接可以在请求和响应之后关闭,以便释放资源。
  • 四次挥手四次挥手原因:一端发送FIN是表示自己不发数据,但是还可以接收另一端发送的数据。所以要结束TCP连接,需要双方都FIN+ACK两次RTT。根据wiki也有可以通过三次挥手结束连接,但是需要同时关闭双端。结束TIME_WAIT需要等待2MSL(最大报文段生存时间)才能到CLOSED状态。一是避免最后的ACK丢白需要重发,二是要确保此次连接的数据包在网络中消失,避免跟下次连接混淆。

请求响应

  • 状态码
  • 1xx:信息响应,表示服务器已经接收到请求,正在处理中。
  • 2xx:成功响应,表示请求已经被成功处理。
  • 200 OK:表示请求已经成功处理,并返回请求的资源。
  • 204 No Content:表示请求已经成功处理,但是响应不包含任何实体信息。
  • 206 Partial Content:表示只返回部分内容,一般用于请求的是大文件的一部分。
  • 3xx:重定向响应,表示客户端需要采取进一步的措施才能完成请求。
  • 301 Moved Permanently:永久性重定向,请求的资源已经被永久移动到新位置。
  • 302 Found:临时性重定向,请求的资源已经被临时移动到新位置。
  • 304 Not Modified:表示客户端缓存的资源仍然有效,可以直接使用。
  • 4xx:客户端错误响应,表示客户端请求包含某种错误或无法完成请求。
  • 400 Bad Request:请求包含语法错误或无法被服务器所识别。
  • 401 Unauthorized:表示请求需要HTTP身份验证。
  • 403 Forbidden:表示请求被服务器拒绝,客户端没有访问权限。
  • 404 Not Found:请求的资源不存在。
  • 5xx:服务器错误响应,表示服务器无法完成请求。
  • 500 Internal Server Error:表示服务器遇到了错误,无法完成请求。
  • 502 Bad Gateway:表示服务器作为网关或代理角色无法从上游服务器接收到有效的响应。
  • 503 Service Unavailable:表示服务器

常用方法

  • GET:用于请求获取资源,可以在请求中添加参数,但是请求头和请求体中传输的数据量有限制。
  • POST:用于提交数据到服务器,不同于GET,POST请求可以在请求体中传输大量数据。
  • PUT:用于更新已有资源,客户端需要向服务器传输整个更新后的资源。
  • DELETE:用于删除服务器上的资源。
  • HEAD:与GET方法类似,但是只返回请求头信息,不返回实际的资源内容。
  • OPTIONS:用于请求获取支持的HTTP方法和服务器支持的特殊功能。
  • CONNECT:用于建立与目标资源的双向通道,通常用于HTTPS加密通信。
  • TRACE:用于追踪请求-响应的传输路径,主要用于调试和测试。

协议特点

  • 简单易用:HTTP协议设计简单,易于实现和使用。
  • 灵活可扩展:HTTP协议支持多种数据格式,可以扩展新的方法和头部字段。
  • 无状态:HTTP协议是无状态的,每个请求都是相互独立的,服务器不会保存客户端的状态信息,每个请求都需要包含足够的信息以便服务器理解。
  • 基于请求和响应模型:HTTP协议是基于请求和响应模型的,客户端发送请求,服务器返回响应。
  • 支持缓存:HTTP协议支持缓存技术,可以减少网络传输量和服务器负载。
  • 明文传输:HTTP协议传输数据是明文的,容易被窃听和篡改,不具备安全性。
  • 支持多种请求方法:HTTP协议支持多种请求方法,包括GET、POST、PUT、DELETE等。
  • 无连接:HTTP协议是无连接的,每个请求都需要建立一个新的连接,处理完毕后立即断开连接。

安全机制

  • 传输安全
  • 机密性 - 防止传输过程中信息被窃听,数据加密
  • 完整性 - 防止传输过程中信息被篡改,数字签名
  • 可信性 - 防止传输过程中信息被伪造,数字证书
  • 加密解密
  • 对称加密算法,对称加密算法使用同一个密钥进行加密和解密,加密和解密速度快,但密钥传输和管理(交易双方都使用同样钥匙,安全性得不到保证)相对困难。常用的对称加密算法有 AES、DES、3DES 等。
  • 代码示例
require 'openssl'

def encrypt(data, key)
  cipher = OpenSSL::Cipher.new('AES-128-CBC')
  cipher.encrypt
  cipher.key = key
  iv = cipher.random_iv
  encrypted = cipher.update(data) + cipher.final
  [encrypted, iv]
end

def decrypt(encrypted_data, key, iv)
  decipher = OpenSSL::Cipher.new('AES-128-CBC')
  decipher.decrypt
  decipher.key = key
  decipher.iv = iv
  decrypted = decipher.update(encrypted_data) + decipher.final
  decrypted
end

key = OpenSSL::Random.random_bytes(16)
data = 'Hello, World!'
encrypted_data, iv = encrypt(data, key)
decrypted_data = decrypt(encrypted_data, key, iv)
puts decrypted_data
  • 非对称加密算法 - 非对称加密算法使用一对密钥进行加密和解密,公钥用于加密,私钥用于解密。非对称加密算法安全性较高,密钥传输和管理相对容易,但加密和解密速度相对较慢。常用的非对称加密算法有 RSA、ECC 等。
  • 代码示例
require 'openssl'

def encrypt(data, public_key)
  public_key.public_encrypt(data)
end

def decrypt(encrypted_data, private_key)
  private_key.private_decrypt(encrypted_data)
end

key_pair = OpenSSL::PKey::RSA.generate(2048)
public_key = key_pair.public_key
private_key = key_pair.private_key
data = 'Hello, World!'
encrypted_data = encrypt(data, public_key)
decrypted_data = decrypt(encrypted_data, private_key)
puts decrypted_data
  • 数字签名 - 是一种对电子文档进行签名的方法,用于验证发送者的身份并确保数据的完整性。签名过程涉及使用私钥对文档的哈希值进行加密。接收者使用相应的公钥解密签名,并与文档的哈希值进行比较,以验证签名的有效性。
  • 数字证书 - 是一种用于验证实体(个人、组织或设备)身份的电子文档。它包含证书所有者的公钥、颁发者(通常是一个权威的证书颁发机构,如 VeriSign 或 DigiCert)、有效期以及其他相关(授权中心名称、证书序列号)信息。数字证书可以确保公钥的真实性,防止中间人攻击。
  • 生成过程
  • 证书持有人生成一对公钥和私钥,将公钥和一些身份信息发送给数字签名认证机构。
  • 数字签名认证机构对证书持有人的身份进行验证,然后使用自己的私钥对证书持有人的公钥进行加密,生成数字签名。
  • 数字签名认证机构将证书持有人的公钥、身份信息和数字签名一起打包成数字证书,发送给证书持有人。
  • 联系
  • 数字证书和数字签名相互依赖,数字证书用于验证公钥的拥有者,而数字签名用于验证文档的来源和完整性。数字签名依赖数字证书的公钥进行验证。
  • 示例
  • 假设Bob想要向Alice发送一条消息,并使用数字签名进行验证。Bob可以按照以下步骤进行:
  • Bob使用哈希函数对要发送的消息进行哈希处理,生成消息的摘要。
  • Bob使用自己的私钥对消息的摘要进行加密,生成数字签名。
  • Bob将消息和数字签名一起发送给Alice。
  • Alice使用Bob的公钥对数字签名进行解密,得到消息的摘要。
  • Alice对接收到的消息进行哈希处理,生成消息的摘要。
  • Alice将得到的消息摘要与数字签名中的摘要进行比较,如果两者相等,则消息通过了验证。
  • 如果Bob没有由数字签名认证机构颁发的数字证书,Alice可能会拒绝接受消息,因为无法验证数字签名的真实性和完整性。
  • TLS/SSL协议
  • 工作流程
  1. 客户端发送「ClientHello」,内容包括:支持的协议版本,比如TLS1.0版,一个客户端生成的随机数Random1(稍后用于生成“会话密钥”),支持的加密算法(如RSA公钥加密)和支持的压缩算法。
  2. 服务端发送「ServerHello」,内容包括:客户端与服务端支持的最高协议版本,一个服务器生成的随机数Random2,CipherSuite与压缩算法(如RSA)。如果是复用session,还会带上session ID。
  3. 服务端发送「ServerCertificate」证书。服务器会将自己的证书下发给客户端,其中Certificates即是证书(除了网站的CA证书外,还一并把该CA证书的中级证书下发,所以是一个证书链),证书内包含公钥。
  4. (双向认证)服务端发送CertificateRequest。请求客户端证书。
  5. 服务端发送「ServerHelloDone」。完成协商。
  6. (双向认证)客户端发送Certificate。包含客户端证书以及公钥。
  7. 客户端发送「ClientKeyExchange」。生成随机数Random3,用证书的公钥加密生成PreMasterSecret。服务端用私钥解密PreMasterSecret得到Random3。
  8. (双向认证)客户端发送CertificateVerify。用客户端证书私钥根据上一个消息生成签名,服务端用客户端公钥解密,确认客户端证书有效。
  9. 双端根据Random1、Random2、Random3用协商的加密算法生成密钥。
  10. 客户端发送「ChangeCipherSpec」。表示之后数据均以加密方式传输。
  11. 客户端发送「Finished」。发送加密的Finished消息,内容是基于前一次消息生成的hash以及Message Authentication Code (MAC)。服务端验证Finished消息是否有效,无效则关闭连接。
  12. 服务端发送「ChangeCipherSpec」以及「Finished」。同上。
  13. 开始加密数据传输。
  • HTTPS,是在 HTTP基础上加入了SSL/TLS 协议进行数据传输加密和身份认证的协议
  • HTTP+加密+认证+完整性保护
  • HTTPS是如何工作的?
  • 根据WireShark分析工作流程

高级特性

  • Session- 是一种在Web应用程序中跟踪用户会话状态的机制。当用户通过Web浏览器访问网站时,服务器为其分配一个唯一的session ID,并将其存储在一个cookie中或者通过URL重写传递给每个请求。在会话期间,服务器可以使用这个ID来存储和检索与该用户相关的数据,如用户的登录状态、购物车内容等。会话通常在用户关闭浏览器或者超时后结束。HTTP session可以使用不同的存储机制,如内存、数据库、文件等,以根据应用程序的需要进行配置。
  • 示例
class ExampleController < ApplicationController

  def index
    username = session[:username]
    if username.nil?
      redirect_to login_path
    else
      # 用户已登录,继续处理请求
      # ...
    end
  end

  def login
    username = params[:username]
    password = params[:password]
    if valid_user?(username, password)
      session[:username] = username
      redirect_to example_path
    else
      redirect_to login_path
    end
  end

  private
  def valid_user?(username, password)
    # 验证用户的用户名和密码是否正确
    # ...
  end
end
  • Cookie - 是一种存储在用户计算机上的小型文本文件,主要用于网站间交换数据以及记录用户访问网站的行为和偏好等信息。当用户访问某个网站时,该网站可以通过设置HTTP Cookie,把一些信息存储在用户的浏览器中。当用户再次访问该网站时,浏览器会将存储在Cookie中的信息发送给该网站,从而实现对用户的识别和个性化服务等功能。Cookie通常包含名称、值、过期时间、路径和域等属性。由于Cookie存储在用户计算机上,因此可能会被恶意软件或黑客攻击窃取,从而对用户的隐私造成威胁。因此,现代浏览器通常会提供一些安全策略,如SameSite属性、Secure属性、HttpOnly属性等,来保护Cookie的安全性。
  • 示例
// 设置Cookie
Set-Cookie: username=johndoe; Expires=Wed, 16 Jun 2023 00:00:00 GMT; Path=/

// 读取Cookie
var username = getCookie("username");

// 删除Cookie
document.cookie = "username=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/;";
  • 分块机制 - 分块传输机制(Chunked Transfer Encoding)是HTTP/1.1中定义的一种传输编码方式,用于在传输过程中动态生成响应内容并将其分割成多个数据块进行传输,以便于在内容长度未知的情况下进行传输。这种机制通常用于实时数据传输和大文件传输等场景。
  • 示例
require 'socket'
server = TCPServer.new('localhost', 8080)

loop do
  client = server.accept

  response_body = "This is the first chunk of data.\n"
  chunk_size = response_body.bytesize.to_s(16)

  response = "HTTP/1.1 200 OK\r\n"
  response += "Content-Type: text/plain\r\n"
  response += "Transfer-Encoding: chunked\r\n\r\n"
  response += "#{chunk_size}\r\n#{response_body}\r\n"

  client.write(response)

  response_body = "This is the second chunk of data.\n"
  chunk_size = response_body.bytesize.to_s(16)
  response = "#{chunk_size}\r\n#{response_body}\r\n"
  response += "0\r\n\r\n"
  client.write(response)
  client.close
end

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the first chunk of data.
1A
This is the second chunk of data.
0
  • 压缩机制 - 一种用于减少传输数据量的技术,它通过压缩响应内容来减少数据传输量,从而提高网络传输效率。常用的HTTP压缩算法有gzip和deflate。gzip算法是一种基于DEFLATE算法的压缩算法,它使用Lempel-Ziv编码(LZ77)和哈夫曼编码来压缩数据。deflate算法也是基于LZ77算法的压缩算法,但它不像gzip算法一样使用哈夫曼编码。
  • 示例
// request
GET /index.html HTTP/1.1
Host: www.example.com
Accept-Encoding: gzip

// server
require 'zlib'

response_body = "This is the response body"
compressed_body = Zlib::Deflate.deflate(response_body, Zlib::BEST_COMPRESSION)

response_headers = {
  'Content-Type' => 'text/plain',
  'Content-Encoding' => 'gzip',
  'Content-Length' => compressed_body.bytesize.to_s
}

response = "HTTP/1.1 200 OK\r\n"
response += response_headers.map { |k, v| "#{k}: #{v}" }.join("\r\n")
response += "\r\n\r\n"
response += compressed_body

client.write(response)

// 客户端发送一个HTTP请求,其中通过Accept-Encoding: gzip请求头告诉服务器它支持gzip压缩算法。
// 服务器收到请求后,如果它也支持gzip压缩算法,就可以将响应内容压缩成gzip格式,然后通过Content-Encoding: gzip响应头告诉客户端它使用了gzip压缩算法。
// 客户端在接收到响应后,如果发现Content-Encoding: gzip响应头,就可以将响应内容解压缩成原始格式。
  • 缓存机制 -指在客户端或服务器上存储响应数据的机制,以便在后续请求中能够更快地获取该数据。HTTP缓存可以减少网络带宽的使用和页面加载时间,提高用户体验。
  • 强制缓存:浏览器在第一次请求资源时,会将该资源缓存到本地,并设置一个过期时间。在过期时间内,浏览器再次请求该资源时,会直接从本地缓存中获取,不会发起请求。常用的强制缓存头字段有Expires和Cache-Control。
  • 协商缓存:当强制缓存过期后,浏览器会向服务器发送请求,并带上上次缓存的响应的信息,服务器根据这些信息来判断是否需要返回新的响应。常用的协商缓存头字段有Last-Modified和ETag。
  • 示例
// 强制缓存,设置过期时间为一小时
Cache-Control: max-age=3600

// 协商缓存,设置Last-Modified和ETag
Last-Modified: Wed, 09 Jun 2021 00:00:00 GMT
ETag: "123456789"

// 客户端请求时带上If-Modified-Since和If-None-Match字段
If-Modified-Since: Wed, 09 Jun 2021 00:00:00 GMT
If-None-Match: "123456789"

升级演变

  • HTTP/2
  • 基本概念 - 一种用于Web传输的协议,它是HTTP/1.1的继任者。
  • 特点
  • 二进制协议:所有的消息在发送时,会进行拆分,分为更小的包和帧,从而通过虚拟信道进行双向消息传输。
  • 多路复用:可以在一个连接上同时传输多个请求和响应,这样可以提高性能。
  • 首部压缩:使用HPACK算法进行首部压缩算法来减少传输的数据量,从而提高性能。
  • 服务器推送:可以让服务器在客户端请求之前推送响应数据,这样可以减少网络延迟,提高性能
  • HTTP/3
  • 协议简介
  • QUIC(Quick UDP Internet Connection)是谷歌推出的一套基于UDP的传输协议,它实现了TCP + HTTPS + HTTP/2的功能,目的是保证可靠性的同时降低网络延迟。因为UDP是一个简单传输协议,基于UDP可以摆脱TCP传输确认、重传、慢启动等因素,建立安全连接只需要一个往返时间,它还实现了HTTP/2多路复用、头部压缩等功能。
  • 协议概览

实践工具

  • 浏览器:浏览器是HTTP最常用的工具,用于访问Web页面和资源。
  • cURL:cURL是一个命令行工具,可以发送HTTP请求并显示响应。
  • Postman:Postman是一个流行的API测试工具,可以发送HTTP请求并查看响应。
  • Wireshark:Wireshark是一个网络协议分析器,可以捕获和分析HTTP流量。
  • Fiddler:Fiddler是一个HTTP调试代理工具,可以捕获和分析HTTP请求和响应。
  • Charles:Charles是一个HTTP代理工具,可以捕获和分析HTTP请求和响应,并进行调试和修改。

培训总结

纸上得来终觉浅,绝知此事要躬行。