众所周知计算机软件的架构目前最为常见的是 B/S 和 C/S 架构,B/S 和 C/S 架构的软件都采用了分层结构,将系统划分为不同的模块层次,每个模块层负责相应功能,这种架构便于管理和维护,同时提高了系统的可扩展性和灵活性。笔者感觉最主要的特点是在使用软件时都会产生数据,而这些数据如果存储在本地时很不安全的,并且用户产生的数据才是开发对应软件公司想用的东西,数据才是一个软件科技公司的财产。两种架构都将用户界面和数据处理分离,有助于系统的灵活性和维护性,用户界面只需要负责展示信息,而数据处理由服务器端或客户端中的逻辑处理模块完成;无论是 B/S 还是 C/S 架构,都涉及客户端和服务器之间的通信,客户端向服务器发送请求,并接收服务器的响应,这种通信机制实现了应用程序的交互和数据交换,这篇博文将探讨一些在 B/S 架构下的网络通信协议技术。
Web 浏览器和客户端
当浏览器发生数据请求就会采用 HTTP 协议和应用服务器交换数据,而应用服务器和数据库服务器交互则采用传输层的 TCP 协议。
HTTP Protocol
HTTP 协议是 HyperText Transfer Protocol 的缩写 (即超文本传输协议),是由 w3c(万维网联盟)制定的一种应用层协议,用来定义浏览器与 Web 服务器之间如何通信以及通信的数据格式。因为 B/S 架构中的通信模块就是以 HTTP 这个协议作为标准协议的,所以对该协议有所了解可以更好的编写程序。 HTTP 协议的发展历史悠久,已经不断的迭代多个版本,不同时期的 HTTP 版本特性,整理表格:
时间段 | HTTP版本 | 主要特点 |
---|---|---|
1989-1995 | HTTP/0.9 | - 最初版本,仅支持 GET 请求。 - 无请求头或状态码,只有响应主体。 - 用于传输 HTML 文件。 |
1996-1999 | HTTP/1.0 | - 引入多种 HTTP 方法(GET、POST、HEAD 等)。 - 引入状态码、请求头、响应头等概念。 - 服务器在每次请求后关闭连接。 |
1999-2015 | HTTP/1.1 | - 引入持久连接,减少连接建立的开销。 - 引入管道化(Pipelining),实现多请求并发。 - 引入 Host 头字段,允许多个域名共享 IP 地址。 - 引入分块传输编码和压缩,提高效率。 |
2015-至今 | HTTP/2.0 | - 完全重新设计,旨在提高性能和效率。 - 改进多路复用,支持并行请求和响应。 - 引入头部压缩,减少数据传输大小。 - 允许服务器推送资源,提高效率。 - 强制使用加密(TLS),提高安全性。 |
2020-至今 | HTTP/3.0 | - 基于 QUIC 协议,进一步提高性能和安全性。 - 改进连接建立速度和稳定性,减少握手延迟。 - 实现数据包级别的错误纠正和拥塞控制。 - 采用基于 UDP 的传输协议。 |
如果要测试 HTTP 协议的一些特性这里推荐使用 telnet
命令行工具,可以在命令行进行 HTTP 数据包封装,Telnet 使用了 TCP/IP 协议进行通讯,Telnet 协议默认是 23 端口。它允许用户通过网络连接到远程主机,并在远程系统上执行命令,就像在本地终端上输入命令一样。完全可以使用 telent 命令行工具,来模拟整个 HTTP 协议连接建立的过程,HTTP 请求和响应的过程如下:
- 浏览器根据 IP 地址和端口号与服务器建立连接
- 向 Web 服务器发送请求数据包
- Web 服务器接收请求数据包后,发送相应的响应数据包
- 浏览器接收响应数据后关闭连接
在 Windows 中的 telent 默认会在高级功能设置中,而 MacOS 和 Linux 用户则需要手动进行安装对应的 telent
命令,下图是一次使用 telent 进行 HTTP/1.1 版本请求响应的例子日志细节。
$: telnet www.ibyte.me 80
Trying 172.67.151.15...
Connected to www.ibyte.me.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 400 Bad Request
Server: cloudflare
Date: Mon, 09 Oct 2023 11:55:59 GMT
Content-Type: text/html
Content-Length: 155
Connection: close
CF-RAY: -
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>cloudflare</center>
</body>
</html>
Connection closed by foreign host.
另外 Keep-Alive 超时间隔时间在各个 Web 服务器配置可以设置,Keep-Alive 机制对应的请求头中的是 Connection
字段,服务器会根据此字断来做相应的处理。
字段 | 作用 |
---|---|
Connection: keep-alive | TCP 持久连接 |
Connection: close | 要求服务器关闭 TCP 连接 |
下面是笔者一个使用 Telnet 例子日志信息:
$: telnet www.ibyte.me 80
Trying 172.67.151.15...
Connected to www.ibyte.me.
Escape character is '^]'.
GET /path1 HTTP/1.1
Host: www.ibyte.me
Connection: keep-alive
GET /path2 HTTP/1.1
Host: www.ibyte.me
Connection: keep-alive
GET /path3 HTTP/1.1
Host: www.ibyte.me
Connection: keep-alive
而 HTTP/2.0 引入了多路复用 Multiplexing 机制,允许客户端同时发送多个 HTTP 请求并在同一个 TCP 连接上进行传输,同时服务器也可以将多个响应并行地返回给客户端,不同请求的数据可以交错传输,而不必等待前面的请求响应完成。这样可以充分利用连接,减少了等待时间,提高了效率;这个机制可以想象为霰弹枪一样,同时可以发射多个子弹,传统步枪只能单道连发,总体来看不同性能提升方案差异对照图。
至于对于具体值和索引,建议查阅 IETF RFC7541 规范文档,如果不是自己去开发实现 HTTP/2.0 协议的话。
全双工通信
通过上面篇幅已经知道 HTTP 只能适用于从客户端主动发起,而服务器只能被动提供服务,对请求做出对应的请求数据响应;当然这里在 HTTP/2.0 允许服务器推送资源,提高效率,HTTP/2.0 会根据客户端请求主动推送对应的数据包到客户端中。在这种架构下客户端和客户端之间不是直接 P2P 方式进行通信的,而是通过服务器进行通信交互数据。典型的全双工通信例子有股票市场的 K 图,或者一些在线的 IM 即时通讯应用,目前 Web 实现这类应用的方案有通过 HTTP 协议进行请求轮训的方式,或者 WebSocket 的方式,这也是本篇技术博客要详细讲解的技术。