HTTP协议
一 何为HTTP协议
HTTP(hypertext transport protocol),即超文本传输协议,用于万维网(WWW:World Wide Web )服务器与本地浏览器之间传输超文本的传输协议(互相通信的规则)。
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。
二 HTTP工作原理
HTTP协议工作于C/S架构模型上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。常见的web服务端有:Apache服务器、Nigix服务器等。
Web服务器根据接收到的请求后,向客户端发送响应信息。HTTP默认端口号为80,可根据实际情况进行修改。
三 HTTP协议特点
3.1 基于TCP/IP
HTTP协议是基于 TCP/IP 协议之上的应用层协议。
3.2 基于请求-响应模式
HTTP协议规定请求从客户端发出,最后服务器端响应该请求并返回。换句话说,肯定是先从客户端开始建立通信的,服务器端在没有接收到请求之前不会发送响应。
3.3 无状态保存
HTTP是一种不保存状态,即无状态 (stateless )协议。 HTTP 协议自身不对请求和响应之间的通信状态进行保存。也就是说在 HTTP 这个级别,协议对于发送过的请求或响应都不做持久化处理。
使用HTTP 协议,每当有新的请求发送时,就会有对应的新响应产生。协议本身并不保留之前一切的请求或响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的。可是随着 Web 的不断发展,因无状态而导致业务处理变得棘手的情况增多了。比如,用户登录到一家购物网站,即使他跳转到该站的其他页面后,也需要能继续保持登录状态。针对这个实例,网站为了能够掌握是谁送出的请求,需要保存用户的状态。 HTTP/1.1 虽然是无状态协议,但为了实现期望的保持状态功能 , 于是引入了 Cookie 技术。有了 Cookie 再用 HTTP 协议通信就可以管理状态了。有关 Cookie 的详细内容后面再进行学习。
3.4 无连接
无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
一句话:HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响应协议。
何为URL?
URL(Uniform Resource Locator),即统一资源定位符,说白了就是一个网址,组成结构如下:
协议名://域名:端口/路径,比如:http://mysite:8080/main/index.html
四 HTTP的工作流程
HTTP的基本交互流程如下图所示:
每个HTTP站点都有一个服务器进程监听着TCP的HTTP端口,HTTP端口默认为80,也可由服务器进程设为其他端口。当服务器发现有客户端建立连接并提交了一个HTTP请求(Request)后,就根据请求的内容执行相应的操作,并将结果返回给客户端(Response)。通常客户在浏览器中发起一次网络访问的步骤如下:
第一步:输入网址并按Enter键,比如访问:http://mysite:8080/main/index.html
第二步:浏览器通过域名查询到真实IP,比如为:172.1.1.1
第三步:向服务器172.1.1.1的8080端口发起TCP连接请求并建立连接
第四步:发送HTTP请求的内容,包括访问的地址:/main/index.html、访问方式GET、浏览器本身的产品名等
第五步:服务器返回/main/index.html中的数据作为Response发送给客户端。如果请求的不是一个文件,则服务器需要执行相应的代码,动态生成且返回给客户端
第六步:浏览器收到结果后关闭与服务器的TCP连接
第七步:浏览器将接收到的结果呈现在显示器上
注意:域名解析本身不是HTTP的一部分,客户端应在向服务器建立TCP连接之前就通过DNS服务器完成域名解析工作。
1.根据域名,进行DNS域名解析; 2.根据解析拿到的IP的地址,建立TCP连接; 3.向IP地址发送HTTP请求; 4.服务器处理请求; 5.返回相应结果; 6.关闭TCP连接; 7.浏览器解析HTML; 8.浏览器布局渲染
以上是最典型的HTTP流程,当今的HTTP版本还允许客户端再一次HTTP请求完成后不关闭TCP连接,以便第二次发送HTTP请求时复用该连接,从而达到减少系统整体开销的目的,此技术在HTTP中叫作keep-alive。
补充--如何查询某一域名的ip地址:
在终端输入要搜索网址,前面加上“PING ”。比如说百度就是:ping www.baidu.com
五 客户端请求消息结构
客户端发送一个HTTP请求到服务器的请求消息包括以下四部分结构:
请求行(request line):请求方式、请求路径、协议和版本,例如:GET /index.html HTTP/1.1
请求头部(header):请求头名称:请求头内容,为key:value格式,例如:Host:localhost
空行:用来与请求体分隔开
请求数据:GET没有请求数据,只有POST有请求数据。
下图给出了请求消息的结构:
GET /favicon.ico HTTP/1.1\ Host: 127.0.0.1:8880 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 Accept: image/webp,image/apng,image/*,*/*;q=0.8 Referer: http://127.0.0.1:8880/ Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9
注:本例中没有消息体
六 HTTP请求方法
在HTTP协议中,请求有很多请求方法,其中最为常用的就是GET和POST。下面列举出所有请求方法,供后期查询学习。
|
序号 |
方法 |
描述 |
|
1 |
GET |
从访问的地址中获取信息,既获取信息头,又获取信息体。这是互联网上最主要的一种HTTP访问方式 |
|
2 |
POST |
客户端通过POST方法向服务器提交新数据,服务器必须保证数据被完整地保存,并且服务器不允许出现重复的POST数据提交。这是HTML中通过表单(Form)提交数据所使用的URL访问方式 |
|
3 |
HEAD |
类似于GET请求,只不过返回的响应中没有具体的内容(消息体),用于获取报头(消息头) |
|
4 |
PUT |
与POST访问方法类似,PUT也是一种客户端向服务器提交数据的方式。但是PUT允许客户端重新提交主键的数据,当通过PUT访问方式在服务器中发现重复主键的数据时,它会用新提交的数据覆盖服务器中已有的数据 |
|
5 |
DELETE |
从给定的地址中删除信息 |
|
6 |
CONNECT |
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器 |
|
7 |
OPTIONS |
为客户端提供一种查询“本URL地址中有哪些可用的访问方式”的方法 |
|
8 |
TRACE |
回显服务器收到的请求,主要用于测试或诊断 |
6.1 GET请求方法
HTTP默认的请求方法是GET,主要有以下特点:
- 没有请求体
- 数据有相应大小限制
- GET请求数据会显示在浏览器的地址栏中
GET请求常用的操作:
- 在浏览器的地址栏中直接给出URL,那么就一定是GET请求
- 点击页面上的超链接一定是GET请求
- 提交表单时,表单默认使用GET请求,但可以设置为POST
请求信息示例如下:
GET /favicon.ico HTTP/1.1 Host: 127.0.0.1:8880 Connection: keep-alive User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 Accept: image/webp,image/apng,image/*,*/*;q=0.8 Referer: http://127.0.0.1:8880/ Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9
- GET /favicon.ico HTTP/1.1:GET请求,请求服务器路径为 /favicon.ico ,协议为1.1;
- Host:127.0.0.1:8880:请求的主机名为127.0.0.1:8880;
- Connection: keep-alive:客户端支持的链接方式,保持一段时间链接,默认为3000ms;
- User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36:与浏览器和OS相关的信息。有些网站会显示用户的系统版本和浏览器版本信息,这都是通过获取User-Agent头信息而来的;
- Accept:image/webp,image/apng,image/*,*/*;q=0.8:告诉服务器,当前客户端可以接收的文档类型,其实这里包含了*/*,就表示什么都可以接收;
- Accept-Language: zh-cn,zh;q=0.9:当前客户端支持的语言,可以在浏览器的工具选项中找到语言相关信息;
- Accept-Encoding: gzip, deflate:支持的压缩格式。数据在网络上传递时,可能服务器会把数据压缩后再发送;
- Referer: http://127.0.0.1:8880/:请求来自哪个页面,例如你在百度上点击链接到了这里,那么Referer:http://www.baidu.com;如果你是在浏览器的地址栏中直接输入的地址,那么就没有Referer这个请求头了;
- Accept-Charset: GB2312,utf-8;q=0.7,*;q=0.7:客户端支持的编码;
- Cookie: JSESSIONID=369766FDF6220F7803433C0B2DE36D98:因为不是第一次访问这个地址,所以会在请求中把上一次服务器响应中发送过来的Cookie在请求中一并发送去过;这个Cookie的名字为JSESSIONID。
Referer请求头是比较有用的一个请求头,它可以用来做统计工作,也可以用来做防盗链。 统计工作:我公司网站在百度上做了广告,但不知道在百度上做广告对我们网站的访问量是否有影响,那么可以对每个请求中的Referer进行分析,如果Referer为百度的很多,那么说明用户都是通过百度找到我们公司网站的。 防盗链:我公司网站上有一个下载链接,而其他网站盗链了这个地址,例如在我网站上的index.html页面中有一个链接,点击即可下载JDK7.0,但有某个人的微博中盗链了这个资源,它也有一个链接指向我们网站的JDK7.0,也就是说登录它的微博,点击链接就可以从我网站上下载JDK7.0,这导致我们网站的广告没有看,但下载的却是我网站的资源。这时可以使用Referer进行防盗链,在资源被下载之前,我们对Referer进行判断,如果请求来自本网站,那么允许下载,如果非本网站,先跳转到本网站看广告,然后再允许下载。
HTTP无状态:无状态是指协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态。从另一方面讲,打开一个服务器上的网页 和你之前打开这个服务器上的网页之间没有任何联系 如果你要实现一个购物车,需要借助于Cookie或Session或服务器端API(如NSAPI and ISAPI)记录这些信息,请求服务器结算页面时同时将这些信息提交到服务器 当你登录到一个网站时,你的登录状态也是由Cookie或Session来“记忆”的,因为服务器并不知道你是否登录 优点:服务器不用为每个客户端连接分配内存来记忆大量状态,也不用在客户端失去连接时去清理内存,以更高效地去处理WEB业务 缺点:客户端的每次请求都需要携带相应参数,服务器需要处理这些参数 容易犯的误区: 1、HTTP是一个无状态的面向连接的协议,无状态不代表HTTP不能保持TCP连接,更不能代表HTTP使用的是UDP协议(无连接) 2、从HTTP/1.1起,默认都开启了Keep-Alive,保持连接特性,简单地说,当一个网页打开完成后,客户端和服务器之间用于传输 HTTP数据的TCP连接不会关闭,如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接 3、Keep-Alive不会永久保持连接,它有一个保持时间,可以在不同的服务器软件(如Apache)中设定这个时间
6.2 post请求方法
特点:
- 数据不会出现在地址栏中
- 数据的大小没有上限
- 有请求体
- 请求体中如果存在中文,会使用URL编码!
Http协议中参数的传输是"key=value"这种键值对形式的,如果要传多个参数就需要用“&”符号对键值对进行分割。如"?name1=value1&name2=value2",这样在服务端在收到这种字符串的时候,会用“&”分割出每一个参数,然后再用“=”来分割出参数值。 针对“name1=value1&name2=value2”我们来说一下客户端到服务端概念上的解析过程: 上述字符串在计算机中用ASCII吗表示为: 6E616D6531 3D 76616C756531 26 6E616D6532 3D 76616C756532。 6E616D6531:name1 3D:= 76616C756531:value1 26:& 6E616D6532:name2 3D:= 76616C756532:value2 服务端在接收到该数据后就可以遍历该字节流,首先一个字节一个字节的进行,当到3D这字节后,服务端就知道前面吃得字节表示一个key,再向后进行,如果遇到26,说明刚才3D到26子节之间的是上一个key的value,以此类推就可以解析出客户端传过来的参数。 现在有这样一个问题,如果我的参数值中就包含=或&这种特殊字符的时候该怎么办。 比如:说“name1=value1”,其中value1的值是“va&lu=e1”字符串,那么实际在传输过程中就会变成这样“name1=va&lu=e1”。我们的本意是就只有一个键值对,但是服务端会解析成两个键值对,这样就产生了歧义。 如何解决上述问题带来的歧义呢?解决的办法就是对参数进行URL编码 URL编码只是简单的在特殊字符的各个字节前加上%,例如,我们对上述会产生奇异的字符进行URL编码后结果:“name1=va%26lu%3De1”,这样服务端会把紧跟在“%”后的字节当成普通的字节,就是不会把它当成各个参数或键值对的分隔符。
POST请求是可以有体的,而GET请求不能有请求体。
- Content-Type: application/x-www-form-urlencoded:表单的数据类型,说明会使用url格式编码数据;url编码的数据都是以“%”为前缀,后面跟随两位的16进制。
- Content-Length:13:请求体的长度,这里表示13个字节。
- keyword=hello:请求体内容!hello是在表单中输入的数据,keyword是表单字段的名字。
七 服务端响应消息结构
HTTP响应也由四个部分组成,分别是:状态行、消息报头、空行和响应正文。
响应内容是由服务器发送给浏览器的内容,浏览器会根据响应内容来显示。遇到<img src=''>会开一个新的线程加载,所以有时图片多的话,内容会先显示出来,然后图片才一张张加载出来。
HTTP/1.1 200 OK # 状态行
Date: Fri, 08 Dec 2017 08:47:56 GMT
Content-Type:text/html;charset=utf-8
Content-Length:0
Server:BWS/1.0
Set-Cookie:BDSVRTM=223; path=/
Set-Cookie:BD_HOME=1; path=/
Set-Cookie:H_PS_PSSID=1456_24886_21119_17001_25178; path=/; domain=.baidu.com # 以上为消息报头:人为组合
# 空行
<!DOCTYPE html> # 响应正文
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
- HTTP/1.1 200 OK:响应协议为HTTP1.1,状态码为200,表示请求成功,OK是对状态码的解释;
- Server:xxx:服务器的版本信息;
- Content-Type: text/html;charset=UTF-8:响应正文使用的编码为UTF-8;
- Content-Length: xx:响应正文为xx字节;
- Set-Cookie: xxxx:响应给客户端的Cookie;
- Date: Wed, 25 Sep 2012 04:15:03 GMT:响应的时间,这可能会有8小时的时区差;
7.1 HTTP状态码
当访问一个网页时,访问者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
常见状态码如下:
- 200:请求成功,浏览器会把响应体内容(通常是html)显示在浏览器中;
- 301:资源被永久转移到其他URL
- 302:重定向,当响应码为302时,表示服务器要求浏览器重新再发一个请求,服务器会发送一个响应头Location,它指定了新请求的URL地址;
- 404:请求的资源没有找到,说明客户端错误的请求了不存在的资源;
- 500:请求资源找到了,但服务器内部出现了错误;
HTTP状态码分类
HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:
|
状态码 |
类别 |
描述 |
|
1** |
Information(信息性状态码) |
表明服务器已经收到request,但需要进一步处理,请客户端等待 |
|
2** |
Success(成功状态码) |
请求正常处理完毕 |
|
3** |
Redirection(重定向状态码) |
请求的地址被重定向,需要客户端重新发起请求 |
|
4** |
Client Error(客户端错误状态码) |
服务器无法处理请求。一般为请求中提交的参数或内容有错误 |
|
5** |
Server Error(服务器错误代码) |
服务器处理请求时出错,一般本类错误需要联系服务器管理员处理 |
更多:HTTP状态码详细列表
7.2 其他报头信息
告诉浏览器不要缓存的报头信息:
- Expires: -1;
- Cache-Control: no-cache;
- Pragma: no-cache;
自动刷新报头信息,浏览器会在3秒之后请求http://www.baidu.com:
Refresh: 3;url=http://www.baidu.com
7.3 HTML中指定报头信息
在HTMl页面中可以使用<meta http-equiv="" content="">来指定报头信息,例如:在index.html页面中给出<meta http-equiv="Refresh" content="3;url=http://www.baidu.com">,
表示浏览器只会显示index.html页面3秒,然后自动跳转到http://www.baidu.com
八 常用头字段
请参考:http://tools.jb51.net/table/http_header





浙公网安备 33010602011771号