HTTP协议
来源:互联网 发布:可米小子诅咒 知乎 编辑:程序博客网 时间:2024/05/22 01:46
什么是HTTP协议
HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程。客户端连上web服务器后,若想获得web服务器中的某个web资源,需遵守一定的通讯格式,HTTP协议用于定义客户端与web服务器通迅的格式。
HTTP协议是学习JavaWeb开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无法管理和维护一些复杂的WEB站点。
HTTP协议的版本
HTTP协议的版本:HTTP/1.0、HTTP/1.1。
HTTP1.0和HTTP1.1的区别
在HTTP1.0协议中,客户端与web服务器建立连接后,只能获得一个web资源。
HTTP1.1协议,允许客户端与web服务器建立连接后,在一个连接上获取多个web资源。
一个问题:一个web页面中,使用img标签引用了三幅图片,当客户端访问服务器中的这个web页面时,客户端总共会访问几次服务器,即向服务器发送了几次HTTP请求?
例,服务器中的web页面为1.html,内容为:
aaaaaaaaaaaaaaaaaaa<img src="1.jpg" /><img src="2.jpg" /><img src="3.jpg" />
此时通过浏览器访问服务器中的1.html。
可发现客户端向服务器发送了4次http请求,第一次获取到整个页面资源。第二次浏览器向服务器要1.jpg,然后依次向服务器要2.jpg、3.jpg。为了减少客户端向浏览器发送的请求数,减少服务器的压力,通常会利用css技术将多张图片归并为一张图片,请求时,只打开这张图片的一小部分。
HTTP请求
HTTP请求包括的内容
客户端连上服务器后,向服务器请求某个web资源,称之为客户端向服务器发送了一个HTTP请求。
一个完整的HTTP请求包括如下内容:
- 一个请求行。
- 若干请求头。
- 实体内容。
范例:
Web服务器通过客户端发送过来的这些请求信息,就可以确定向请求者回送什么资源,以及根据客户端的环境信息采用什么方式进行回送等。
HTTP请求的细节——请求行
请求行中的GET称之为请求方式,请求方式有:
- POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT
- 常用的有: GET、 POST
- 用户如没有设置,默认情况下浏览器向服务器发送的都是get请求,例如在浏览器直接输地址访问,点超链接访问等都是get,用户如想把请求方式改为post,可通过更改表单的提交方式实现。
不管POST或GET,都用于向服务器请求某个WEB资源,这两种方式的区别主要表现在数据传递上:
- 如请求方式为GET方式,则可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔,例如:
GET /mail/1.html?name=abc&password=xyz HTTP/1.1
。
GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。 - 如请求方式为POST方式,则可以在请求的实体内容中向服务器发送数据,POST方式的特点:传送的数据量无限制。
HTTP请求的细节——请求头
HTTP请求中的常用消息头。
- Accept:用于告诉服务器,客户机支持的数据类型。
- Accept-Charset:用于告诉服务器,客户机支持的编码。
- Accept-Encoding:用于告诉服务器,客户机支持的数据压缩格式。
- Accept-Language:客户机的语言环境。
- Host:客户机通过这个头告诉服务器,想访问的主机名。
- If-Modified-Since:客户机通过这个头告诉服务器,资源的缓存时间。
- Referer:客户机通过这个头告诉服务器,它是从哪个资源来访问服务器的(用于防盗链上)。
- User-Agent:客户机通过这个头告诉服务器,客户机的软件环境。
- Cookie:客户机通过这个头可以向服务器带些数据。
- Connection:客户机通过这个头告诉服务器,请求完了之后是保持连接(Keep-Alive)还是断开连接(close)。
- Date:当前请求时间值。
例,
Host: localhost:8080User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:47.0) Gecko/20100101 Firefox/47.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateConnection: keep-aliveIf-Modified-Since: Thu, 07 Jul 2016 02:57:42 GMTIf-None-Match: W/"19-1467860262148"
HTTP响应
HTTP响应包括的内容
一个HTTP响应代表服务器向客户端回送的数据,它包括:
- 一个状态行
- 若干响应头
- 实体内容
范例:
在一个HTTP响应中,WEB服务器通过响应头向web客户端描述客户端的请求成功与否,以及它所发送的数据类型等一些信息,客户端通过这些信息,进而可以知道如何对数据进行处理。
HTTP响应的细节——状态行
状态行格式:HTTP版本号 状态码 原因叙述<CRLF>
。例:HTTP/1.1 200 OK
。
状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类,如下所示:
这里还是细说几个常见的状态码:
- 302——你是客户机,我是服务器,你请求我,我要你去找别人。要找哪个人,等一会我会给你回送一个location的头,location指定的是哪个地址,意味着要你去找谁。
- 307/304:和缓存相关,你是客户机,我是服务器,你请求我,意味着我要你去拿缓存里面的数据显示。
- 404——意味着请求的资源在web服务器里面没有,请求的地址可能写错了。
- 403——你开始访问服务器某个资源,传入用户名和密码,结果用户名没有权限,服务器有这个资源,但拒绝给你这个资源。
HTTP响应细节——常用响应头
HTTP响应中的常用响应头(消息头):
- location:这个头配合302状态码使用,用于告诉客户找谁。
- Server:服务器通过这个头,告诉浏览器服务器的类型。
- Content-Encoding:服务器通过这个头,告诉浏览器数据的压缩格式。
- Content-Length:服务器通过这个头,告诉浏览器回送数据的长度。
- Content-Language:服务器通过这个头,回送数据(即浏览器)的语言环境。
- Content-Type:服务器通过这个头,告诉浏览器回送数据的类型。
- Last-Modified:服务器通过这个头,告诉浏览器当前资源的缓存时间。
- Refresh:服务器通过这个头,告诉浏览器隔多长时间刷新一次。
- Content-Disposition:服务器通过这个头,告诉浏览器以下载方式打开数据。
- Transfer-Encoding:服务器通过这个头,告诉浏览器数据的传送格式。
- Set-Cookie:和Cookie相关的。以后会详讲。
- ETag:缓存相关的头。
服务器有很多web资源,每一个web资源根据其内容生成一个唯一的串(标识符),内容不同,标识符也不同。当浏览器访问服务器资源时,那服务器会把此资源的标识符以ETag方式的形式回写给客户机,客户机下次来访问服务器时,会带着ETag头来,服务器收到这个标识符之后,它会检查一下资源的标识符和客户机带过来的标识符是不是一样,如果是一样,意味着此资源没有被改动,没有被改动,直接就让浏览器去拿缓存;如果客户机带过来的标识符和服务器资源的标识符不一样,那么此资源就做出改动了,因为内容一改动,标识符就会跟着改,这时,服务器给浏览器回送改动后的资源。
用ETag可以做到实时更新,其他头只能控制到秒一级的更新,无法做到实时性很高的系统。 - Expires:服务器通过这个头,告诉浏览器把回送的资源缓存多长时间,-1或0,则不缓存。
- Cache-Control: no-cache
- Pragma: no-cache
服务器通过以上两个头,也是控制浏览器不要缓存数据。(实时性要求很高的数据不能缓存,如股票数据,对于一般的数据,都可缓存。)
如果控制市面上所有的浏览器都不要缓存数据,最好设置Expires、Cache-Control、Pragma这三个响应头。 - Connection:响应完之后,是保持连接,还是断开连接。
- Date:当前响应时间值。
在服务端设置响应头来控制客户端浏览器的行为
新建一个动态web项目——day04,该项目的结构图如下:
设置Location响应头,实现请求重定向
@WebServlet("/ServletDemo1")public class ServletDemo1 extends HttpServlet { // 用location和302实现请求重定向 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setStatus(302); response.setHeader("location", "/day04/1.html"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
当在浏览器中使用URL地址http://localhost:8080/day04/ServletDemo1
访问ServletDemo1时,就可以看到服务器作出响应后发送到浏览器的状态码和响应头信息,如下图所示:
服务器返回一个302状态码告诉浏览器,你要的资源我没有,但是我通过Location响应头告诉你哪里有,而浏览器解析响应头Location后知道要跳转到/day04/1.html页面,所以就会自动跳转到1.html,如下图所示:
设置Content-Encoding响应头,告诉浏览器数据的压缩格式
压缩数据的好处:
- 假设数据有1M,浏览器为了显示这个资源,要从服务器上下载1M的数据,才能打开整个页面,打开速度就慢,你如果一压缩,可能1M的数据只有300K,对浏览器而言,只需要接收300K的数据就可打开整个页面,所以压缩会提供整个页面的访问性能。
- 为了省钱,因为大型的网站,比如新浪、搜狐这样的门户网站,电信对它们的收费是按照出口流量收费的,出去了多少数据,电信找它们收多少钱,为了省钱,数据在发出去的时候一定要压缩,不压缩就亏大发了。
怎么实现数据的压缩?需要使用GZIPOutputStream流来压缩数据。
@WebServlet("/ServletDemo1")public class ServletDemo1 extends HttpServlet { // 压缩数据输出 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; System.out.println("原始数据大小:"+data.getBytes().length); ByteArrayOutputStream bout = new ByteArrayOutputStream(); GZIPOutputStream gout = new GZIPOutputStream(bout); gout.write(data.getBytes()); /* * GZIPOutputStream:包装流,一般都会有一个缓冲, * 如果调用其write()方法在写数据时, * 如果数据量没有把包装流的缓冲写满,它是不会往底层流写的。 */ gout.close(); // 一定要有 // 得到压缩后的数据 byte[] gzip = bout.toByteArray(); System.out.println("压缩后的数据大小:"+gzip.length); /* * 将压缩数据发送给浏览器 */ // 通知浏览器数据采用压缩格式 response.setHeader("Content-Encoding", "gzip"); // 告诉浏览器回送的压缩数据的长度 response.setHeader("Content-Length", gzip.length+""); response.getOutputStream().write(gzip); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
服务器发给浏览器的响应信息如下:
此时Eclipse控制台打印如下信息:
设置content-type响应头,控制浏览器以哪种方式处理数据
@WebServlet("/ServletDemo1")public class ServletDemo1 extends HttpServlet { // 通过Content-Type头字段,控制浏览器以哪种方式处理数据 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Content-Type", "image/jpeg"); // 读取位于项目根目录下的Krystal.jpg这张图片,返回一个输入流 InputStream in = this.getServletContext().getResourceAsStream("/Krystal.jpg"); int len = 0; byte[] buffer = new byte[1024]; OutputStream out = response.getOutputStream(); while((len=in.read(buffer)) != -1) { out.write(buffer, 0, len); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
提示:Content-Type头字段对应的值可通过tomcat服务器下conf/web.xml文件查找。
服务器发给浏览器的响应信息如下:
ServletDemo1的运行结果如下图所示:
在浏览器中显示出了图片。
设置refresh响应头,让浏览器定时刷新
@WebServlet("/ServletDemo1")public class ServletDemo1 extends HttpServlet { // 定时刷新 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // response.setHeader("Refresh", "3"); // 浏览器每隔3秒钟请求一次 response.setHeader("Refresh", "3;url='http://www.sina.com'"); // 浏览器隔3秒钟请求一次后,并刷新到新浪上去 String data = "aaaaaaaaaaaaaaaaaaaaaaaa"; response.getOutputStream().write(data.getBytes()); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
设置content-disposition响应头,让浏览器下载文件
@WebServlet("/ServletDemo1")public class ServletDemo1 extends HttpServlet { // 定时刷新 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Content-Disposition", "attachment;filename=Krystal.jpg"); InputStream in = this.getServletContext().getResourceAsStream("/Krystal(4).jpg"); int len = 0; byte[] buffer = new byte[1024]; OutputStream out = response.getOutputStream(); while((len=in.read(buffer)) != -1) { out.write(buffer, 0, len); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); }}
在浏览器中访问ServletDemo1就会弹出文件下载框,如下图所示:
可保存到桌面上。
HTTP的一个实用头字段——Range
HTTP请求头字段
Range头指示服务器只传输一部分web资源。这个头可以用来实现断点续传功能。Range字段可以通过三种格式设置要传输的字节范围:
- Range:bytes=1000-2000
传输范围从1000到2000字节。 - Range:bytes=1000-
传输web资源中第1000个字节以后的所有内容。 - Range:bytes=1000
传输最后1000个字节。
例,web服务器有一个资源,比如是a.txt,内容为:
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
有一个用户下载了一部分数据,并存储到C盘中的a.txt,内容为:
aaaaa
此时该用户想接着下载完剩下的数据,该怎么做呢?此时他就不能通过浏览器去访问了,而应该自己写程序去访问指定的资源。
public class RangeDemo { public static void main(String[] args) throws Exception { URL url = new URL("http://localhost:8080/day04/a.txt"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("Range", "bytes=5-"); InputStream in = conn.getInputStream(); int len = 0; byte[] buffer = new byte[1024]; FileOutputStream out = new FileOutputStream("c:\\a.txt", true); while((len=in.read(buffer)) != -1) { out.write(buffer, 0, len); } in.close(); out.close(); }}
运行以上程序,该用户就下载完剩下的数据了。
HTTP响应头字段
Accept-Ranges:这个字段说明web服务器是否支持Range,支持则返回Accept-Ranges: bytes
;如果不支持,则返回Accept-Ranges: none
。
Content-Range:指定了返回的web资源的字节范围。这个字段值的格式是——例,Content-Range: 1000-3000/5000
。
注意:HTTP响应头字段不常用。
- HTTP协议
- http协议
- HTTP协议
- HTTP协议
- HTTP协议
- http协议
- HTTP协议
- HTTP协议
- HTTP协议。。。
- HTTP协议
- HTTP协议
- HTTP协议
- HTTP协议
- HTTP协议
- http协议
- HTTP协议
- http协议
- HTTP协议
- 嵌入式C学习笔记(二) 编译器-GCC的工作过程
- php中的break,continue,return,exit,die等跳出或终止循环笔记
- POJ 3784 Running Median
- EC-JET喷码机回收管无回收
- equals和==的区别
- HTTP协议
- 5.2.6 I/O核心子系统
- js第二节
- ZOOKEEPER的ZAB协议
- 输入n个整数,输出其中最小的k个
- springMVC视图层和控制器层之间参数传递
- JSP文件上传在servlet收集参数的详解
- linux lftp命令 详解
- Mysql 主主互备