HTTP的构成与请求过程
先看一下URI,URL,URN是什么:
URI
URI
,全称Uniform Resource Identifier
,统一资源标识符
。
URL
URL
, 全称Uniform Resource Location
,统一资源定位符
。通过URL我们可以准确的定义一个资源的位置。
如http://www.baidu.com/sb.jpg
,http为协议名,中间www.baidu.com
为主机的域名,后面为资源的名称。
URN
Uniform Resource Name
,统一资源名。URN只需要知道一个域名就可以访问到资源,而URL一般域名变更,就需要更新URL,URN比较方便。
HTTP请求格式
http_request_format.png
HTTP请求由请求行、请求头、空行、请求体组成。
Request Line
Request Line的结构为:
Request_Line = Method SP Request-URL SP HTTP-Version CRLF
Method 请求方法,GET、POST、PUT、DELETE、
SP是分隔符,就一个字节大小,值为0x20,对于ASCII码中的空格。
Request-URL实例传输的时候有两种可能,一种是完整的absoluteURI,包含Schema(http)和Host,另一种是abs_path,Host部分被移交到了Header中。
HTTP-Version也很直观,文本展示形式为:HTTP/1.1,代表我们当前使用的版本。
CRLF由两个字节组成。CR值为16进制的0x0D,对应ASCII中的回车键,LF值为0x0A,对应ASCII中的换行键,CRLF合起来就是我们平常所说的\r\n。
Header
header本质上是一些文本键值对,形式:Key:空格 Value CRLF。
Body
body包含请求的实际数据。
对于Get来说,body体是空的,或者说不存在。
HTTP Response
http_response
Status Line的结构如下:
Status-line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
重点在Status Code的理解
1XX 正在响应请求
2XX 成果
3XX 重定向
4XX 客户端错误
5XX 服务器错误
Body的解析
body解析本身比较简单,从header中知道Content_Length之后,读取固定长度的字节流即完成了body的获取,关键的环节是获取之后,如何读取其中的数据并传递交给应用层。HTTP本身并没有对Body中的内容编码做约束,而是把它交给协议的使用者去决定,场见的Content-Type有:
- application/octet-stream 二进制流
- application/json Json格式数据
- application/x-www-form-urlencoded 默认Content-Type
- multipart/form-data
一些隐藏的细节
从上面可以看出,http是一种基于文本解析的协议,上面提到的空行(0x20)、换行(0x0D0A)都是HTTP用来做文本解析的辅助符号。
解析HTTP的text的一个简化流程,当我们从TCP层拿到应用层的buffer之后,以CLRF(\r\n)为分隔符,将整个buffer分成若干行,第一行自然是Request Line,之后每一行代表一个Header,如果连续读两个CLRF,则表示header结束,如果是Method=POST,读取header中Content-Length值,最后根据这个值读取固定长度的body体。
HTTP 请求过程
HTTP的请求过程,以浏览器访问一个网址为例。
- 用户输入URL
- 客户端通过DNS解析 查询到目标服务器的IP地址
- 客户端与查询到的IP地址建立TCP连接
- 连接成功后,浏览器构造一个HTTP请求给服务器
- 服务端从数据库查询数据并封装成一个HTTP响应给浏览器
- 浏览器对响应内容进行数据解析、提取、渲染展示。
HTTP协议的请求和响应都必须遵循固定的格式,否则服务端无法正确解析客户端的请求,客服端也无法解析不同网址的响应内容。