每天上网浏览网页的的背后到底是什么样子的。

Web客户端

工作流程:客户端向服务端发送请求Request,服务端给客户端发送响应Response。

服务器与资源URL

服务器存放不同类型的Web资源[1]。而要定位一个位于互联网上的资源,需要URI - Uniform Resource Identifier(统一资源标识符)。它有两种形式:

  • URL - Uniform Resource Locator(统一资源定位符):描述某资源的特定位置。(基本是这种)
  • URN - Uniform Resource Name(统一资源名):作为特定内容的唯一名称使用,与目前的资源所在位置无关。(未大范围使用)

URL语法(9个组成部分)

<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
abc://username:password@example.com:123/path/data;type=test?key=value&key2=value2#ref

URL编码和字符集:URL通过“专义”使用百分号(%)后面紧跟两个表示字符ASCII码的十六进制数,来表示URL中不安全字符。

HTTP报文

无论是客户端给服务端的请求,还是服务端给客户端的响应,传递的都是HTTP报文。HTTP报文的组成包括:起始行、首部字段、主体。[2]

http_request_response

方法 - Request报文中的方法:

方法 描述 是否包含主体
GET 获取文件
HEAD 获取文档的首部
POST 发送需要处理的数据
PUT 将请求的主体部分存储在服务器
TRACE 对可能经过代理服务器传送到服务器上去的报文进行追踪
OPTION 决定可以在服务器上执行哪些方法
DELETE 从服务器删除一份文档

状态码 - Response报文中的状态码:

类别 原因短语
1XX (100 ~ 101) Informational(信息性状态码) 接手的请求正在处理
2XX (200 ~ 206) Sucess(成功状态码) 请求正常处理完毕
3XX (300 ~ 305) Redirection(重定向状态码) 需要进行附加操作以完成请求
4XX (400 ~ 415) Client Error(客户端错误状态码) 服务器无法处理请求
5XX (500 ~ 505) Server Error(服务器错误状态码) 服务器处理请求出错

首部 - 报文中的各种首部:

类别
通用首部
请求首部
响应首部
实体首部

HTTP连接管理

HTTP报文的传输层协议为TCP,网络层协议IP。在HTTP客户端向服务端发送请求报文前,需要用IP协议地址和端口号在客户端和服务器之间建立一条TCP/IP连接。<源IP地址、源端口号、目的IP地址、目的端口号>唯一定义了一条连接。

最初Unix系统提供了套接字API向HTTP程序员隐藏了TCP和IP的所有细节,程序员可以使用套接字API创建TCP端点数据结构、建立TCP连接、对数据流进行读写[3]。

HTTP是在建立的TCP连接之上,所以HTTP的性能取决于底层的TCP通道的性能。HTTP的网络延迟[4]。

http_timeline

通常一个Web页面需要发起多次HTTP请求来获取全部信息。如果使用串行方式,上图中的性能延迟就会叠加起来。为了提高HTTP的连接性能,有如下几种方式:

  • 并行连接:通过多条TCP连接发起并发的HTTP请求[5]
  • 持久连接:重用TCP连接,以消除连接及关闭时延[6]
  • 管道化连接:通过共享的TCP连接,发起并发的HTTP请求[7]
  • 复用的连接:交替传送请求和响应的报文(实验阶段)

3_http_cnnection


参考资料:

  • 《HTTP权威指南》第一部分(第1 ~ 第4章):HTTP-web的基础

注[1]:HTTP协议给Web传输对象打上MIME - Multipurpose Internet Mail Extension(最初用于邮件,HTTP采纳用于标记多媒体内容类型)

注[2]: HTTP协议的版本有0.9、1.0、1.1、2.0。现在主要是HTTP/1.1。

注[3]:现在几乎所有操作系统和语言中都提供此API功能。常见的API有:

套接字API调用 描述
s = socket()
bind(s, )
connect(s, )
listen(s, …) 标识一个本地套接字,使其可以合法接受连接
s2 = accept(s) 等待某人连接一条到本地端口的连接
n = read(s, buffer, n)
n = write(s, buffer, n)
close(s)
shutdown(s, )
getsockopt(s, …)
setsockopt(s, …)`

注[4]:首先确定IP地址,可能需要通过DNS查找IP地址;然后客户端向服务器建立TCP连接;第三步,连接建立后客户端向服务端发送HTTP请求;第四步,服务器处理请求,这步可能很快;第五步,服务器向客户端发送响应报文;第六步,客户端关闭TCP连接。

注[5]:浏览器确实是发起多条并行连接,但是会保持在一个较小的数量(如4条)。如果每个客户端都并行发起多条连接,web服务器会承受不了,性能反而会下降。

注[6]:初始化了对某服务器HTTP请求的应用程序很可能在将来一段时间内对此台服务器发起更多的请求。在事务处理结束后仍然保持在打开状态的TCP连接被称为持久连接。持久连接有两种类型,HTTP/1.0中的keep-alive和HTTP/1.1中的persistent。

注[7]:在响应到达之前,可以将多条请求放入队列。