学习笔记,非纯原创
HTTP (HyperText Transfer Protocol,超文本传输协议)
是基于 TCP 的应用层协议,通信方式是 client / server 模式。HTTP 报文 (HTTP packet)
分为两种:请求报文(request packet)
和 回复报文(response packet)
。
1. 请求报文
请求报文由客户向服务器发送,报文由三个部分组成,即请求行、首部行和实体主体。
CRLF: 回车换行 1CRLF
是 Carriage-Return Line-Feed
的缩写,意思是回车换行
。http 请求报文每行都是 CRLF 结尾。
在 C 语言编程中,回车 (\r) 和换行 (\n) 使用时的主要区别在于
- \r 会回到当前行的行首,如果接着输出的话,本行旧的内容会被覆盖
- \n 将光标转到下一行的起始位置,不会回到行首
二者的出现要回溯到计算机还没有出现之前,有一种叫做电传打字机的外设,每秒钟可以打 10 个字符。但是它有一个问题,就是打完一行换行的时候,要用去 0.2 秒,正好可以打两个字符。要是在这 0.2 秒里面,又有新的字符传过来,那么这个字符将丢失。
于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符,即为回车 (carriage return)
— 告诉打字机把打印头定位在左边界,换行 (line feed)
- 告诉打字机把纸向下移一行。
计算机发明后,这两个概念也就被搬到了计算机上。那时存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是就出现了分歧:
- Unix 系统里,每行结尾只有 \n
- Windows 系统里面,每行结尾是 \n\r
- Mac 系统里,每行结尾是 \r。
一个直接后果是,Unix/Mac 系统下的文件在 Windows 里打开的话,所有文字会变成一行;而 Windows 里的文件在 Unix/Mac 下打开的话,在每行的结尾可能会多出一个 ^M 符号。
1.1. 请求行
请求报文的开始行称为请求行,包含请求方法、请求 URL 和 HTTP 版本三个字段。每个字段都以空格分隔。 比如:GET / HTTP/1.1
,请求方法为 GET
,请求 URL 为/
,HTTP 版本为 HTTP/1.1
。
方法就是对所请求的对象进行的操作,实际上就是一些命令。因此请求报文的类型是由它所采用的方法决定的。
请求报文的一些方法
- GET:当客户端要从服务器中读取文档时,使用 GET 方法请求读取由 URL 所标志的信息。使用 GET 方法时,请求参数和对应的值附加在 URL 后面,利用一个问号 “?” 代表 URL 的结尾与请求参数的开始,传递参数长度受限制。例如,
/index.jsp?id=100&op=bind
。 - POST:当客户端给服务器提供信息较多时可以使用 POST 方法。POST 方法将请求参数封装在 HTTP 请求数据中,以名称 / 值的形式出现,可以传输大量数据。
- HEAD:请求读取由 URL 所标志的信息的首部
- DELETE: 删除指明的 URL所标志的资源
GET 和 POST 的区别
- GET没有body,POST有body,body中有若干字符串,首部行中的Content_Length标记着body的长度
- GET不安全,POST比较安全
- GET的参数长度有限制,而POST的参数长度没有限制,是因为 GET 的参数在URL中,而 POST 的参数是在实体主体中
- GET的参数可见,POST的参数不可见
1.2. 首部行
首部行包含用于说明浏览器、服务器或报文主体的一些信息,以键值对的形式存储。整个首部行结束时,还有一个空行将首部行和后面的实体主题分开。
首部行中的一些字段
- Content-Length: 标记着body的长度,
- User-Agent: 标记浏览器类型和操作系统的版本
- Contet-Type: 标记着数据类型(text/html等)
- Host: 客户端告知服务器,所请求的资源是在哪个主机的那个端口上
- Cookie: 用于在客户端存储少量信息,通常用于实现会话(session)功能
- Accept-Language: 标记着用户所使用的语言
- Keep-Alive:time:标记着连接的时间
- Connection:close 此时表示是非持久连接
- Connection:keep-alive 此时表示是持久连接
1.3. 实例
下面是一个完整的 HTTP 请求报文实例。其中请求行使用了相对 URL(省略了主机域名)是因为 Host 首部行给出了主机域名。
一般请求报文不使用实体主体。
GET /dir/index.htm HTTP/1.1 # 请求行使用了相对URL
Host: www.xyz.edu.cn # 首部行的开始,给出了主机的域名
Connection: close # 告诉服务器传送完请求的对象后就关闭 TCP 连接
User-Agent: Mozilla/5.0 # 表明用户代理是使用火狐浏览器
Accept-Languag: cn # 表明用户优先得到中文版本的文档
# 请求报文的最后还有一个空行,标识首部行的结束
2. 回复报文
2.1. 状态行
响应报文是服务器给客户端发送的,用来回复客户端的请求。第一行称为状态行,包含 HTTP 版本、状态码(status code)以及描述操作状态的原因短语。
比如:HTTP/1.1 200 OK
。 HTTP 版本为 HTTP/1.1
,数字状态码是 200
,原因短语是 OK
,表示请求成功。
状态码
状态码都是三位数字的,分为 5 大类:
- 1XX:通知信息,服务器收到请求,需要请求者继续执行操作
- 2XX:成功,操作被成功接收并处理
- 3XX:重定向,需要进一步的操作以完成请求
- 4XX:客户端错误,请求包含语法错误或无法完成请求
- 5XX:服务器错误,服务器在处理请求的过程中发生了错误
2.2. 响应头部
与请求头部类似,为响应报文添加了一些附加信息。
常见响应头部
- Server:服务器应用程序软件的名称和版本
- Content-Type:响应正文的类型(是图片还是二进制字符串)
- Content-Length:响应正文长度
- Content-Charset:响应正文使用的编码
- Content-Encoding:响应正文使用的数据压缩格式
- Content-Language:响应正文使用的语言
2.3. 实例
下面是一个http 报文实例,可以注意到,在实体主体部分返回了请求的页面
HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache/2.2.14 (Win32)
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
Content-Length: 88
Content-Type: text/html
Connection: Closed
<html>
<body>
<h1>Hello, World!</h1>
</body>
</html>
3. 参考资料
- TinyHTTPd 源码分析
- httpserver–如何解析HTTP请求报文
- 谢希仁.计算机网络 (第七版)(2017).