HTTP超文本传输协议

Posted by Young Ken on 2018-10-13

HTTP超文本传输协议

HTTP概述

超文本传输协议(HyperText Transfer Protocol, HTTP)是一种为分布式,合作式,多媒体信息系统服务,面向应用层的协议。

HTTP的历史

HTTP/0.9 (单行协议)

HTTP是1990年问世的,现在的HTTTP/0.9指的是就是HTTP/1.0之前的版本。

1
GET /mypage.html
HTTP/1.0

HTTP/1.0是1996年5月份被正式定义出来,现在还有好多的服务器端在使用。

HTTP/1.1

HTTP/1.1版本,是1997年1月被发布出来的,最大的改进是把Keep-Alive变成了默认选项,使管线化(pipelining)成为可能。

HTTP的特点

  • 简单的

    因为HTTP的头消息都是简单易读读的。

  • 可扩展性

    HTTP中头部是可扩展的,常见的请求头加token。

  • 无状态性

    用一个客户端的两个请求是完全没有关系的,也就是HTTP不具备保存上个请求状态的功能。这样在开发中就有一些麻烦,比如一个客户端已经登录,我从新打开客户端,这个时候客户端又要从新登录,这样就很麻烦。

  • HTTP的链接

    在HTTP/0.9的时候,每发一次链接就要进行TCP的握手,然后再TCP断开链接,这是没有链接保持的。但是到了HTTP/1.0版本加入一个Keep-Alive的头,这样就不用每一次请求都进行握手和断开链接了,但是这个属性不是默认有的,需要客户端主动添加。在HTTP/1.1版本就默认添加了。

协议参数

HTTP版本

HTTP使用”<主要>.<次要>”的编号方案表示协议版本。当发送端有性能提升的时候或者增加了消息的语义增加次要版本号,当消息体有实质的变化的时候增加主版本号,因为1.0的版本和1.1的版本消息实体没有发生变化,因此没有添加大的版本号,但是2.0和1.1大版本号发生了变更,消息实体一定发生了变化。

1
HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT

例子:

1
HTTP/0.9, HTTP/1.0

统一资源标识符(URI)

统一资源标识符(Uniform Resource Identifier,URI)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对网络中(一般指万维网)的资源通过特定的协议进行交互操作。

1
scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]
1
2
3
4
5
authority path
┌───────────────┴───────────────┐┌───┴────┐
abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
└┬┘ └───────┬───────┘ └────┬────┘ └┬┘ └─────────┬─────────┘ └──┬──┘
scheme user information host port query fragment

统一资源定位符(URL)

统一资源定位符URL地址(Uniform Resource Locato,URL),有时也被俗称为网页地址网址)。

URL的scheme常见的有httphttpsftptelnet等等。

HTTP的URL
1
2
3
4
5
authority path
┌───────────────┴───────────────┐┌───┴────┐
http://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
└┬┘ └───────┬───────┘ └────┬────┘ └┬┘ └─────────┬─────────┘ └──┬──┘
scheme user information host port query fragment

很多同学说,我没有用过后user information,这个是个比较含糊的问题,在HTTP1.1规范中没有对这个明确的定义,没有说用,也没有说不让用,没办法之下我们参考了伟大的okhttp框架,这个框架中的注释给了我一些启发。

1
2
3
<h4>Username and Password</h4>
<p>Username and password are either present, or the empty string {@code ""} if absent. This class offers no mechanism to differentiate empty from absent. Neither of these components are popular in practice. Typically HTTP applications use other mechanisms for user identification and authentication.

简单的意思就是最好不要用user information,通常,HTTP应用程序使用其他机制进行用户识别和身份验,也就是我们常用的token。

fragment

fragment可以为空,但是fragment不会被发送到服务器,那么他有什么用呢?

  • 可以跳转到相应的标题下,点击下面的这个标题会跳转到3.2.2
  • 滚动到新的位置但是不加载网页

媒体类型

互联网媒体类型(Internet media type,也称为MIME类型MIME type)或内容类型content type))是给互联网上传输的内容赋予的分类类型。

1
2
3
media-type = type "/" subtype *( ";" parameter )
type = token
subtype = token

一个MIME类型包括一个类型(type),一个子类型(subtype)。此外可以加上一个或多个可选参数(optional parameter)。其格式为

常见的类型有applicationaudioimagemultiparttextMultipartvideo

子类型名有textjsonxmlform-data等等。

常见的媒体类型有application/jsonapplication/xmltext/htmlaudio/mp4application/octet-stream任意二进制文件。

字符集

字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集名称:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。

字符编码(Character encoding)、字集码是把字符集中的字符编码为指定集合中某一对象,以便文本在计算机中存储和通过通信网络的传递。

在计算机早期的时候字符集字符编码是同一回事情,因为ASCII 占用了7个bit,最高未用0表示,(也就是128个字符)也就是一个byte,这样字符集等于字符编码,但是到了现代编码的时代,一个字符集对应多个字符编码方式。

在HTTP中我们用的是字符编码

HTTP消息(Message)

HTTP消息是服务器和客户端之间交换数据的方式。有两种类型的消息︰ 请求–由客户端发送用来触发一个服务器上的动作;响应–来自服务器的应答。

一般的消息体是这样的:

1
2
3
4
generic-message = start-line
*(message-header CRLF)
CRLF
[ message-body ]

  • 消息也都有一个start-line,我们通常叫做起始行,起始行是单独的一行,不可用省略。
  • message-header是一个可选的,可以省略,也可以有多个。
  • 每个消息头都有一个空行进行分割。
  • 最后由一个可选的消息体组成。

HTTP 请求

HTTP请求是由客户端发出的消息,用来使服务器执行动作。

1
2
3
4
5
6
Request = Request-Line
*(( general-header
| request-header
| entity-header ) CRLF)
CRLF
[ message-body ]

请求起始行(Request-Line)

1
Request-Line = Method SP Request-URI SP HTTP-Version CRLF
  • HTTP 方法(Method),常见的有getpostputdelete
  • 请求的uri(Request-URI),通常是一个 URL,或者是协议、端口和域名的绝对路径,通常以请求的环境为特征。
  • HTTP 版本 (HTTP version)。

请求头

请求头包括三个方面,general-headersrequest-headerentity-header

  • general-headers,适用于整个报文。

    Transfer-EncodingDataConnection

  • entity-header,适用于请求的 实体。显然,如果请求中没有任何 实体,则不会发送这样的头文件,包括的内容有

    Content-Length, Content-Language, Content-Encoding

  • request-header

HTTP 响应

在接收并解释请求消息之后,服务器以HTTP响应消息进行响应。

1
2
3
4
5
6
Response = Status-Line
*(( general-header
| response-header
| entity-header ) CRLF)
CRLF
[ message-body ]

状态行(Status-Line)

表示当前的请求的状态。

1
Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
  • HTTP 版本 (HTTP version)。
  • 状态码,表明请求是成功或失败。200404等等。
  • 状态文本,一个简短的,纯粹的信息,通过状态码的文本描述,帮助人们理解该 HTTP 消息。

请求头

参考同HTTP请求的请求头。

请求体

响应的最后一部分是 body。不是所有的响应都有 body:具有状态码 (如 201204的响应,通常不会有 body。

说明

  • 在下面的内容中HTTP规范如果不强调指的就是HTTP1.1规范
  • DIGIT = <任意数字0,1,…9>
  • * = 元素前面的字符*表示重复。完整形式是 * 元素,表示元素的至少和最多次出现。默认值为0和无穷大,因此“*(元素)”允许任何数字,包括零; “1*元素”至少需要一个;并且“1 * 2element”允许一个或两个。
  • N rule = 具体重复:“(元素)”相当于“ *(元素)”;也就是说,(元素)恰好出现。因此,2DIGIT是一个2位数字,3ALPHA是一个由三个字母字符组成的字符串。
  • [rule] = 方括号包含可选元素; “[foo bar]”相当于“* 1(foo bar)”。