HTTP网络请求原理 (二) Http报文格式解析

请求报文

不同的请求方式,它们的请求格式可能是不一样的,请求格式就是我们所说的报文格式. 但是,通常来说一个HTTP请求报文由请求行(request line),请求头部(head),空行和请求数据4个部分组成,下图给出了请求报文的一般格式.
这里写图片描述

  1. 起始行
    报文的第一行就是起始行,在请求报文中用来说明要以什么方式做什么请求,而在响应报文中粗略说明了报文的执行结果.
  2. 首部字段
    起始行后面有零个或多个首部字段. 每个首部字段都包含一个名字和一个值,为了便于解析,两者之间用冒号(如Connection: keep-Alive)来分隔. 首部以一个空行结束. 添加一个首部字段和添加新行一样简单.
  3. 主体
    首部字段的空行之后就是可选的报文主体了,其中包含了所有类型的数据. 请求主体中包括了要发送给Web服务器的数据; 响应主体中装载了要返回给客户端的数据. 起始行和首部都是结构化的文本形式,而主体则可以包含任意的二进制数据(如图片,视频,音轨,软件程序). 当然,主体中也可以包含文本.

下面我们就来学习常用的GET,POST,PUT,DELETE四种请求方式的报文格式.

我们首先学习比较简单的GET和DELETE请求方式,对于DELETE和GET来说,由于它们的功能是删除和获取,因此,只要将URL构造为要处理的资源即可. 也就是说它们所有的参数附加在资源URL的最后,第一个参数前通过”?”符号连接,然后请求参数按照”参数名=参数值”的形式进行追加,每个参数之间用”&”连接. 例如 http://www.myhost.com/image?id=123&fotmat=png ,该URL的参数有id和format,它们的值分别为123和png,如果该请求是DELETE,那么将删除 http://www.myhost.com/image 下id为123,格式为png的图片,如果是GET,那么则是获取该图片. 需要注意的是,GET和DELETE的URL最大长度为1024字节,也就是1KB.

在浏览器中输入 http://www.devtf.cn/?p=909 ,这是开发技术前线第十九期周报的URL,得到的请求报文如下所示:

GET /?p=909 HTTP/1.1
Host: www.devtf.cn
Cache-Control: no-cache

根据上述的HTTP请求格式可知,第一行为请求行,代表请求方式是GET,子路径为/?p=909,也是表示参数p的值为909,HTTP版本为1.1 , 后两行是请求的HEADER区域,第一个请求头是主机地址,值www.devtf.cn. 另外还有一个Cache-Control的请求头,值为no-cache. GET,DELETE请求的所有参数都附加在URL链接中,因此,请求数据部分为空.

对于PUT和POST来说,他们的报文格式一般是表单形式,也就是说这两个请求方式的参数存储在报文的请求数据(报文主体)的位置上:

POST /api/feed/ HTTP/1.1
Accept-Encoding: gzip
Content-Length: 225873
Content-Type: multipart/form-data; boundary=OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Host: www.myhost.com
Connection: Keep-Alive

--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="username"
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Mr.Simple
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp
Content-Disposition: form-data; name="images";
filename="/storage/emulated/0/Camera/jdimage/1xh0e3yyfmpr2e35tdowbavrx.jpg"
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

这里是图片的二进制数据,数据太长,在此省略
--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp--

上述请求的含义为向 www.myhost.com/api/feed/ 这个地址发送一个POST请求. 这个请求的数据格式(Content-Type)为multipart/form-data,报文的boundary值为OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp. 该报文有两个参数,一个参数是文本类型的username参数,值为Mr.Simple,另一个是名为images的二进制参数,数据是一张图片的二进制数据,这里我们将图片的二进制数据省略了.

需要注意的是,一个参数是以两个横杠加上boundary开始的,然后是该参数的一些属性信息,例如参数名,格式等,然后加上一个空行,最后才是参数的值. 例如上述的username参数,完整的格式为:

--OCqxMF6-JxtxoMDHmoG5W5eY9MGRsTBp                          // 两个横杠加上boundary值
Content-Disposition: form-data; name="username"                 //这3个是请求参数的Header属性
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
                                                                        //这里是一个不可省略的空行
Mr.Simple                                                               //这是参数值

POST与PUT都必须遵循这种的格式,每个参数以两个横杠和boundary分隔,参数header与参数值之间有一个空行. 另一个要注意的地方是,请求数据的最后是两个横杠+boundary值+两个横杠作为整个报文的结束符. 当手动构建POST请求报文时,这些格式就尤为重要,如果格式不正确,那么服务端将无法正确解析你的请求.

响应报文

HTTP响应也由3个部分组成,分别是:状态行,消息报头,响应正文. 如下所示,HTTP响应的格式与请求的格式十分类似:

<状态行>
<响应报文header>
<空行>
[响应报文内容]

正如你所见,在响应中唯一真正的区别在于第一行中用状态信息代替了请求信息. 状态行(status line)通过提供一个状态码来说明所请求的资源情况.

状态行格式如下:

HTTP-Version Status-Code Reason-Phrase CRLF

其中,HTTP-Version表示服务器HTTP协议的版本; Status-Code表示服务器发回的响应状态代码; Reason-Phrase表示状态代码的文本描述. 状态代码由3位数字组成,第一个数字定义了响应的类别,且有5种可能取值,如下表所示.

取值范围 含义
100~199 指示信息: 表示请求已接受,继续处理
200~299 请求成功: 表示请求已被成功接收,理解,接收
300~399 重定向: 要完成请求必须进行更进一步的操作
400~499 客户端错误: 请求有语法错误或请求无法实现
500~599 服务器端错误: 服务器未能实现合法的请求

常见状态代码,状态描述的说明如下.

  • 200 OK: 客户端请求成功.
  • 400 Bad Request: 客户端请求有语法错误,不能被服务器所理解.
  • 401 Unauthorized: 请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用.
  • 403 Forbidden: 服务器收到请求,但是拒绝提供服务.
  • 404 Not Found: 请求资源不存在,举个例子: 输入了错误的URL.
  • 500 Internal Server Error: 服务器发生不可预期的错误.
  • 503 Server Unavailable: 服务器当前不能处理客户端的请求,一段时间后可能恢复正常,举个例子: HTTP/1.1 200 OK (CRLF).

例如,这是一个GET请求的Response返回示例:

HTTP/1.1 200 OK
Date: Sat, 31 Dec 2005 23:59:59 GMT
Content-Type: text/html;charset=
Content-Length: 122

<html>
    <head>
        <title>开发技术前线<title>
    head>
    <body>
        <!-这里是Body -->
    <body>
html>

该请求返回码为200,表示请求成功. 返回的数据类型为text/html,编码为ISO-8859-1,内容长度为122. 在一个空行之后就是返回的数据, 也就是一个html页面,也就是一个html页面. 客户端接受到这个返回结果之后,直接将结果展示到WebView上即可. 如果返回的是Json,XML格式的数据,那么,我们通常需要解析这些数据,并且将根据结果进行其他相应的处理.

常见的请求头部

请求头部由键值对组成,每行一对,关键字和值用英文冒号”:”分隔. HTTP规范定义了几种首部字段,应用程序也可以随意发明自己所用的首部. HTTP收不可以分为以下几类,如下表所示.

首部类型 作用
通用首部 既可以出现在请求报文中,也可以出现在响应报文中
请求首部 提供更多有关请求的信息
响应首部 提供更多有关响应的信息
实体首部 描述主体的长度和内容,或者资源自身
扩展首部 HTTP规范中没有定义的新首部

请求头部通知服务器关于客户端请求的信息,典型的请求头有:

  • Content-Type: 请求数据的格式.
  • Content-Length: 消息长度.
  • Host: 请求的主机名,允许多个域名同处一个IP地址,即虚拟主机.
  • User-Agent: 发出请求的浏览器类型,可以自行设置.
  • Accept: 客户端可识别的内容类型列表.
  • Accept-Encoding: 客户端可识别的数据编码.
  • Connection: 允许客户端和服务器指定与请求/响应连接与有关的选项,例如:设置为Keep-Alive则表示保持连接.
  • Transfer-Encoding: 告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式.

你可能感兴趣的:(Android,Java,Socket)