http(hypertext transfer protocol)就是超文本传输协议,它是现代互联网最重要也是最基本的协议。http协议是无状态的、应用层协议,它是web开发的基础,如果想从事web方面的开发,一定要仔细学习一下这个协议。
http设计的目的就是支持客户端(一般是浏览器)和服务器端进行方便的沟通,它是一个b/s协议。因为在互联网中,一个服务器往往需要处理大量的客户端请求,http协议应该尽可能少的占用系统资源。 为了达到这个目的,http协议被设计成无状态的。http协议是在tcp/ip之上的一种协议(http属于应用层,tcp/ip属于运输层),默认端口采用的是80。
http协议栈:

我们把http协议中通信的两方称作client和server(或host),client向server端经过http协议发送一个request,server端收到request后经过一些列的处理返回client一个response,整个过程如下图所示:
我们现在用到的版本是http/1.1,它比1.0版本添加了更多特性。其中比较重要的特性有:
在详细介绍http协议之前我们先看一下url。对于url我想大家都已经很熟悉了,我们如果访问一个网站,我们不需要了解http协议,我们只需要在浏览器中输入这个网站的url即可。web传输的核心就是请求消息,而请求消息就是通过url进行定义的。 url(uniform resource locator) 地址用于描述一个网络上的资源,基本格式如下:
scheme:指定低层使用的协议,一般是http,如果强调安全的话可以是http
host:http服务器的ip地址或者域名
port:http服务器的默认端口是<code>80</code>,这种情况下端口号可以省略。如果使用了别的端口,必须指明
path:访问资源的路径
url-params:url的参数
query-string:发送给http服务器的数据
anchor:锚
当你在浏览器输入url<code>http://www.website.com</code>的时候,浏览器发送一个request去获取<code>http://www.website.com</code>的html。服务器把response发送回给浏览器。浏览器分析response中的 html,发现其中引用了很多其他文件,比如图片,css文件,js文件。
浏览器会自动再次发送request去获取图片,css文件,或者js文件。当所有的文件都下载成功后, 网页就被显示出来了。
我们通过url告诉了浏览器我们去哪个网站(主机)获得资源,而我们要在这个网站上做什么操作呢?这个具体的操作就是由请求method定义的。当然,客户端可以对服务器做多种类型的操作,为此<code>http1.1</code>协议共定义了八种标准操作:
get:向指定的资源发出“显示”请求。使用get方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在web application中。其中一个原因是get可能会被网络蜘蛛等随意访问。
post:向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。
put:向指定资源位置上传其最新内容。
delete:请求服务器删除request-uri所标识的资源。
options:这个方法可使服务器传回该资源所支持的所有http请求方法。用’*’来代替资源名称,向web服务器发送options请求,可以测试服务器功能是否正常运作。
head:与get方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
trace:回显服务器收到的请求,主要用于测试或诊断。
connect:<code>http/1.1</code>协议中预留给能够将连接改为渠道方式的代理服务器。通常用于ssl加密服务器的链接(经由非加密的http代理服务器)。
method名称是区分大小写的。当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码<code>405(method not allowed)</code>,当服务器不认识或者不支持对应的请求方法的时候,应当返回状态码<code>501(not implemented)</code>。
其中的get、post、put、delete这四种method分别对应者对远程服务资源的增、删、改、查操作,而其中最长用的是get和post。
get请求的数据会附在url之后(就是据放置在http协议头中),以“?”分割url输数据,多个参数用“&”连接;例如:<code>login.action?name=tom&password=securiy</code>。
post会把提交的数据放置在是http包的正文中。上文示例中<code>name=professional&id=11101</code>就是实际的传输数据;
http协议没有对传输的数据和url长度进行限制, 但特定浏览器和服务器对url长度有限制, 因此对于get提交时,传输数据就会受到url长度的限制; 由于post操作不是通过url传值,理论上数据长度不受限。
post的安全性要比get的安全性高,通过get提交数据,用户名和密码将明文出现在url上,容易被他人看到,url信息也可能会被记录到历史纪录中。
get实例:
post 实例:
通过url和method,客户端就可以发送一个完整的请求给服务端。当然服务端也会做出响应。状态码就是非常重要的一种响应,客户端通过状态码就可以了解服务端做出何种响应。<code>http/1.1</code>中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别:
1xx 提示信息; 表示请求已被成功接收,告诉客户端可以继续发送下一个请求了,若如果已发送完毕可以忽略它。
2xx 成功
3xx 重定向; 要完成请求必须进行更进一步的处理
4xx 客户端错误;请求有语法错误或请求无法实现
5xx 服务器端错误;服务器未能实现合法的请求
最常见的response处理成功之后返回的状态码:
http/1.1 200 ok (crlf)
至此,我们已经了解到了url、verb、status code相关概念,而这些信息就是组成http消息体的主要信息,下面我们就具体看一下http消息体的具体结构。
http消息分为request和response两种消息,http协议对这两种消息定义了如下结构:
从上面定义我们可以看到,http的request和response消息都是由三部分组成:
对于start-line,又分为:
对于headers则有如下几种:
下面我们再用两幅图具体看一下request和response的消息格式:
request消息格式定义:
response消息格式定义:
通过上面介绍我们已经http消息的headers共分为三种,分别是<code>general headers</code>、<code>entity headers</code>、<code>request/response headers</code>。
我把被request和response共享的headers成为general headers,具体有:
cache -control指定请求和响应遵循的缓存机制。
connection 允许客户端和服务器指定与请求/响应连接有关的选项
date 提供日期和时间标志,说明报文是什么时间创建的
pragma头域用来包含实现特定的指令,最常用的是pragma:no-cache
trailer 如果报文采用了分块传输编码(chunked transfer encoding) 方式,就可以用这个首部列出位于报文拖挂(trailer)部分的首部集合
transfer-encoding 告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式
upgrade 给出了发送端可能想要”升级”使用的新版本和协议
via 显示了报文经过的中间节点(代理,网嘎un)
entityheaders主要用来描述消息体(message body)的一些元信息,具体有:
其中,以content为前缀的headers主要描述了消息体的结构、大小、编码等信息,expires描述了entity的过期时间,last-modified描述了消息的最后修改时间。
这部分内容放在下面的request消息体和response消息体中介绍。
通过上面介绍,我们对request消息体结构已经有了大体了解,本节我们再深入介绍一下。
request-line是request消息体的第一部分,其具体定义如下:
其中<code>sp</code>代码字段的分隔符,<code>http-version</code>一般就是<code>"http/1.1"</code>,后面紧接着是一个<code>换行</code>。
在<code>request-line</code>后面紧跟着的就是<code>headers</code>。我们在上面已经介绍了<code>general headers</code>和<code>entity headers</code>,下面便是<code>request headers</code>定义:
<code>request headers</code>扮演的角色其实就是一个request消息的调节器。需要注意的是若一个headers名称不在上面列表中,则默认当做<code>entity headers</code>的字段。
前缀为<code>accept</code> 的headers定义了客户端可以接受的媒介类型、语言和字符集等。<code>from</code>, <code>host</code>, <code>referer</code> 和<code>user-agent</code> 详细定义了客户端如何初始化request。前缀为<code>if</code> 的headers规定了服务器只能返回符合这些描述的资源,若不符合, 则会返回<code>304 not modified</code>。
若<code>request-line</code>中的<code>method</code>为<code>get</code>,请求中不包含消息体,若为<code>post</code>,则会包含消息体。
response消息格式和request类似,也分为三部分:<code>response-line</code>、<code>response headers</code>、<code>response body</code>。
response-line具体定义如下:
<code>http-version</code>字段值一般为<code>http/1.1</code>
<code>status-code</code>前面已经讨论过了
<code>reason-phrase</code> 是对<code>status code</code>的具体描述
一个最常见的response响应为:
http/1.1 200 ok
下面是<code>response-header</code>的定义:
<code>age</code> 表示消息自server生成到现在的时长,单位是秒
<code>etag</code> 是对entity进行md5 hash运算的值,用来检测更改
<code>location</code> 被重定向的url
<code>server</code> 服务器标识
参考资料:
<a href="http://code.tutsplus.com/tutorials/http-the-protocol-every-web-developer-must-know-part-1--net-31177">http://code.tutsplus.com/tutorials/http-the-protocol-every-web-developer-must-know-part-1–net-31177</a>
<a href="https://zh.wikipedia.org/wiki/%e8%b6%85%e6%96%87%e6%9c%ac%e4%bc%a0%e8%be%93%e5%8d%8f%e8%ae%ae">https://zh.wikipedia.org/wiki/%e8%b6%85%e6%96%87%e6%9c%ac%e4%bc%a0%e8%be%93%e5%8d%8f%e8%ae%ae</a>