HTTP 协议是互联网的基础协议,也是网页开发的必备知识,本文将详细的讲述HTTP协议
网络基础TCP/IP
为了理解HTTP,我们有必要事先了解一下TCP/IP协议族。通常使用的网络(包括互联网)是在TCP/IP协议族的基础上运作的。而HTTP属于它内部的一个子集。
TCP /IP 是Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、Internet国际互联网络的基础,由网络层的IP协议和传输层的TCP协议组成。
- TCP/IP的分层管理
TCP/IP协议族重要的一点就是分层。TCP/IP协议族分为4层,从上至下分别是:应用层、传输层、网络层和数据链路层。而HTTP处于应用层。数据从应用层发下来,会在每一层都会加上头部信息,进行封装,然后再发送到数据接收端。
- 三次握手
三次握手是什么?
TCP是面向连接的通信协议,通过三次握手建立连接,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在TCP/IP协议中,TCP协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换TCP窗口大小信息。
- TCP标志位
让我们先来了解一下TCP的一些标志。
ACK:此标志表示应答域有效,就是说TCP应答号将会包含在TCP数据包中;有两个取值:0和1,为1的时候表示应答域有效,反之为0;
SYN:表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1。一台安全的主机将会强制要求一个连接严格的进行TCP的三次握手;
FIN: 表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了,发送FIN标志位的TCP数据包后,连接将被断开。
- 第一次握手:建立连接。客户端发送一个TCP标志位SYN=1、ACK=0的数据包给服务器,并且随机生成一个Sequence Number(同步序列号)为x,等待服务器确认;
- 第二次握手:服务器收到客户端的SYN报文段,需要对这个SYN报文段进行确认,所以向客户端发送答应号ACK=1、SYN=1、确认号Acknowledge number=x+1,还会产生一个随机的序列号Sequence Number为y;
- 第三次握手:客户端收到服务器的SYN+ACK报文段。收到数据后检查Acknowledge number是否是x+1的值,以及ACK的值是否为1,以此来确认是否被服务器正确响应,若正确,客户端会发送ACK=1、确认号码Acknowledge number=y+1,告诉服务器,你的请求连接被确认,连接可以建立。完成TCP三次握手。
完成了三次握手,客户端和服务器端就可以开始传送数据。
- 那么问题来了,为什么是三次握手而不是两次握手、四次握手呢?
其实无非就是既要保证数据可靠传输,又要提高传输的效率,而三次握手酒能满足上述条件;
在网上看到一段很有意思的解释:
三次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,今天balabala……”
两次握手:
“喂,你听得到吗?”
“我听得到呀”
“喂喂,你听得到吗?”
“草,我听得到呀!!!!”
“你TM能不能听到我讲话啊!!喂!”
“……”
四次握手:
“喂,你听得到吗?”
“我听得到呀,你听得到我吗?”
“我能听到你,你能听到我吗?”
“……不想跟傻逼说话”
所以,建立TCP连接是三次握手而不是两次、四次或者其他。
HTTP协议
HTTP 是基于 TCP/IP 协议来传递数据的应用层协议,它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。
- HTTP/0.9
最早版本是1991年发布的0.9版。该版本极其简单,只有一个命令GET,没有在通讯中指定版本号,且不支持请求头。由于该版本不支持POST方法,因此客户端无法向服务器传递太多信息。并且协议规定,服务器只能回应HTML格式的字符串,不能回应别的格式,服务器发送完毕,就关闭TCP连接。
HTTP/1.0
1996年5月,HTTP/1.0 版本发布,内容大大增加。
首先,任何格式的内容都可以发送。这使得互联网不仅可以传输文字,还能传输图像、视频、二进制文件。这为互联网的大发展奠定了基础。
其次,除了GET方法,还引入了POST方法和HEAD方法,丰富了浏览器与服务器的互动手段。- HEAD方法:它与GET方法几乎是一样的,对于HEAD请求的回应部分来说,它的HTTP头部中包含的信息与通过GET请求所得到的信息是相同的。利用这个方法,不必传输整个资源内容,就可以得到Request-URI所标识的资源的信息。该方法常用于测试超链接的有效性,是否可以访问,以及最近是否更新。
HTTP/1.1
1997年1月,HTTP/1.1 版本发布,只比 1.0 版本晚了半年。它进一步完善了 HTTP 协议,一直用到了20年后的今天,直到现在还是最流行的版本。
HTTP/1.1是当前主流的 HTTP 协议。完善了之前 HTTP 设计中的结构性缺陷,明确了语义,添加和删除了一些特性,支持更加复杂的的 Web 应用,最大变化,就是引入了持久连接(persistent connection),即TCP连接默认不关闭,可以被多个请求复用。Keep-Alive模式:
从上面的分析来看,启用Keep-Alive模式肯定更高效,性能更高。因为避免了建立/释放连接的开销。
既然开启了Keep-Alive之后,TCP连接默认不关闭,那么,TCP连接又是什么时候才断开的呢?- 使用消息首部字段Content-Length,故名思意,Content-Length表示实体内容长度,客户端(服务器)可以根据这个值来判断数据是否接收完成。但是如果消息中没有Content-Length,那该如何来判断呢?又在什么情况下会没有Content-Length呢?
- 使用消息首部字段Transfer-Encoding,当客户端向服务器请求一个静态页面或者一张图片时,服务器可以很清楚的知道内容大小,然后通过Content-length消息首部字段告诉客户端 需要接收多少数据。但是如果是动态页面等时,服务器是不可能预先知道内容大小,这时就可以使用Transfer-Encoding:chunk模式来传输 数据了。即如果要一边产生数据,一边发给客户端,服务器就需要使用”Transfer-Encoding: chunked”这样的方式来代替Content-Length。
URL
HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息
URL,全称是UniformResourceLocator, 中文叫统一资源定位符,是互联网上用来标识某一处资源的地址。以下面这个URL为例,介绍下普通URL的各部分组成:
http://www.aspxfans.com:80/news/index.asp?boardID=5&ID=24618&page=1#name
从上面的URL可以看出,一个完整的URL包括以下几部分:
协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP,HTTPS等等本例中使用的是HTTP协议。在”HTTP”后面的“//”为分隔符
域名部分:该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用
端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口
虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”
文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。
锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分
HTTP请求
HTTP 请求由四部分组成:
请求行:包含请求方法、请求地址和 HTTP 协议版本
消息报头:包含一系列的键值对
空行:消息报头后面的空行是必须的
消息主体(可选):注意和消息报头之间有一个空行
下面是一个 HTTP GET 请求的例子:
其中,GET 是请求方法,表示从服务器获取资源。常用的方法还有POST、PUT、DELETE、HEAD、OPTIONS等;/teacher/login?islogin=1 是一个请求地址;HTTP/1.1 表明 HTTP 的版本是 1.1。
Host: 请求资源所在的服务器,它通常从 HTTP URL 中提取出来;
Connection: 表示连接状态,keep-alive 表示该连接是持久连接(persistent connection),即 TCP 连接默认不关闭,可以被多个请求复用,如果客户端和服务器发现对方有一段时间没有活动,就可以主动关闭连接;
Cache-Control: 用于指定缓存指令,它的值有 no-cache, no-store, max-age 等,max-age=秒表示资源在本地缓存多少秒;
Pragma: 主要使用 Pramga: no-cache,相当于 Cache-Control: no-cache。
Upgrade-Insecure-Requests: 该指令用于让浏览器自动升级请求从http到https,用于大量包含http资源的http网页直接升级到https而不会报错.简洁的来讲,就相当于在http和https之间起的一个过渡作用.
User-Agent: 用于标识请求者的一些信息,比如浏览器类型和版本,操作系统等。
Accept: 用于指定客户端希望接受哪些类型的信息,比如 */*表示任何类型, type/* 表示该类型下的所有子类型, text/html, image/gif 等;
Referer: 浏览器向 WEB 服务器表明自己是从哪个 网页/URL 获得/点击 当前请求中的网址/URL。
Accept-Encoding: 浏览器申明自己接收的编码方法,通常指定压缩方法,是否支持压缩,支持什么压缩方法(gzip,deflate,compress,identity表示不进行编码)
Accept-Language: 浏览器申明自己接收的语言 语言跟字符集的区别:中文是语言,中文有多种字符集,比如big5,gb2312,gbk等等。
Cookie: 用于维护状态,可做用户认证,服务器检验等,它是浏览器储存在用户电脑上的文本片段;
响应:
HTTP状态码
HTTP 状态码分成了五大类
1XX信息性状态码:消息已经收到,继续处理
2XX成功:请求已成功被服务器正常处理了
3XX重定向状态码:表明浏览器需要执行某些特殊的处理以正确处理请求
4XX客户端错误状态码:很多客户端错误码是直接由浏览器处理的,如请求含有词法错误或者无法被执行,但是也有些是由服务器处理的,比如404
5xx服务器端错误:服务器未能实现合法的请求常见的状态码
200 OK //客户端请求被服务器正常处理了
204 No Content //服务器接收端请求已成功处理,但在返回的响应报文中不含有实体的主体部分,一般用在只需要客户端往服务器发送信息,而对客户端不发送新信息内容的情况下使用
301 Moved Permanently //永久性重定向,表示请求的资源已被分配了新的URI,服务器发送一个重定向状态码和一个可选的Location Header, 告诉客户端新的资源地址在哪,浏览器客户端会自动用Location中提供的地址,重新发送新的Request
302 Found //302和301 非常相似, 一个是永久转移,一个是临时转移。301,302对用户来说没有区别,他们看到效果只是一个跳转,浏览器中旧的URL变成了新的URL。页面跳到了这个新的url指向的地方。尽量使用301,因为302可能会有URL规范化及网址劫持的问题
304 Not Modified //客户的缓存资源是最新的, 要客户端使用缓存
307 Temporary Redirect //与302有着相同的含义
400 Bad Request //客户端请求有语法错误,不能被服务器所理解
403 Forbidden //服务器收到请求,但是拒绝提供服务
404 Not Found //请求资源不存在,eg:输入了错误的URL。除此之外,也可以在服务器拒绝请求且不想说明理由时使用后
500 Internal Server Error //服务器发生不可预期的错误,有可能是web应用存在bug或某些临时的故障
503 Server Unavailable //服务器当前不能处理客户端的请求(由于超载或停机维护)。通常,这只是暂时状态
Server: 服务器信息,图例中是 Nginx 服务器
Content-Type: 用于指定发送给浏览器的响应正文的媒体类型,比如 text/html, text/css, image/png, image/jpeg, video/mp4, application/pdf, application/json 等;
Content-Encoding: WEB服务器表明自己使用了什么压缩方法(gzip,deflate)压缩响应中的对象,内容编码目的是优化传输内容大小,通俗地讲就是进行压缩。一般经过 gzip 压缩过的文本响应,只有原始大小的 1/4
Transfer-Encoding: Content-Encoding 和 Transfer-Encoding 二者是相辅相成的,对于一个 HTTP 报文,很可能同时进行了内容编码和传输编码。
Keep-Alive: timeout=5, max=100; timeout:过期时间5秒,max是最多一百次请求,强制断掉连接,就是在timeout时间内又有新的连接过来,同时max会自动减1,直到为0,强制断掉