Http协议

  对于一个浏览器,如果它要访问web资源,那就要通过HTTP协议来访问。

  一个高级程序员,那么他肯定对于Http相应有很深的理解,可以这么说“如果你不理解HTTP协议,那你就不用学web程序了;如果你非常了解HTTP协议,那你也不用学web了,因为什么,因为web程序就那么点东西”,下面开始介绍HTTP协议。

  HTTP协议总体来说一共分为两大类,1.请求头 2.响应头,

  一.先说请求头:

  

  请求行:GET是以get方式请求,请求的资源是/lav/1.html,HTTP的版号是1.1,http协议一共有两个版本号,分别是http1.0和http1.1,

  消息头:

    1.Accept:用来告诉服务器,客户端支持的数据类型,这里是全支持,举个例子:text/html,images

    2.Accept-Charset:用于告诉服务器,客户端采用的编码方式,例如:ISO-8859-1

    3.Accept-Encoding:用于告诉服务器,客户机支持的数据压缩格式,这里是gzip格式

    4.If-Modified-Since:用于告诉服务器,这是最后一次的缓存时间,一般的情况下,浏览器第一次在访问页面的时候会本地缓存,这个字段可根据服务最后一次更新的时间来比对,是否重新加载。

    5.Accept-Lanaguage:客户机的语言环境,可用作本地化。

    6.Host:客户机通过这个头告诉服务器,想访问那台主机。

    7.Referer:客户机通过这个头告诉服务,它是从那个资源来访问服务器的(用这个referer可以做“防盗链”),防盗链是什么,比如从别人的网站点击我的网站资源,在这种情况下可以避免直接的打开或者下载,一般情况下应用这个防盗链调回我网站的首页。

    8.User-Agent:客户机通过这个来告诉服务器,客户机的软件环境。

    9.Cookie:客户机通过这个头向服务器带给一些信息。

    10.Connection:客户机通过这个头来确定我这次请求完成,连接是否关闭。(close/Keep-Alive).

  以上就是消息头主要常用的几个头,还有很多,我们只说常用的。

  二.在说响应头:

   

  状态行:http协议的版本号,200状态码,原因叙述

      状态码

      100-199——————表示成功接受请求,要求客户端继续提交下一次请求才能完成整个的处理过程

      200-299——————表示成功接受请求,并已完成整个的处理过程

      300-399——————未完成请求,客户需要进一步细化请求,例如请求的资源已经移动一个新的地址,302(你请求,我要你去找别人),304和307要客户机去拿缓存。

      400-499——————客户端请求有错误,

      500-599——————服务器端出现错误

  多个响应头:

    Location:这个头配合302状态码使用,用于告诉客户机去找谁

    Server:服务器通过这个头告诉浏览器服务器的类型

    Content-Encoding:服务器通过这个头告诉浏览器,我要的数据压缩格式

    Content-Length:服务器通过这个头,告诉浏览器回送数据压缩的长度

    Content-Type:服务器通过这个头告诉浏览器回送数据的类型

    Last-Modified:用来告诉浏览器缓存时间。

    Transfer-Encoding:告诉浏览器数据的传送方式

    refresh:控制浏览器多长时间刷新一次(股票,聊天室)

    content-disposition:服务器通过这个头告诉浏览器数据以下载方式打开数据

    Etag: 和缓存相关的头,这个能保证"实时更新",用在对实时更新要求比较高的网站

    Expires:服务器通过这个头告,诉浏览器回送的资源缓存多上时间,-1,0代表不缓存,date

    cache-control: no cache 和 Pragma: no cache :服务器通过这个两个头告,诉浏览器不要缓存数据

      如果你想市面上的所有的浏览器不缓存你的数据,Expires,cache-control,Pragma都写上就可以了。

   未完待续---21:33

    下面代码演示,看一看响应头有什么作用,这里面我把测试代码都放在了方法里,如果你想测试别的,复制,或者引用都行,

    

  1 package com.du.servlet;
  2 
  3 import java.io.ByteArrayOutputStream;
  4 import java.io.File;
  5 import java.io.FileOutputStream;
  6 import java.io.IOException;
  7 import java.io.InputStream;
  8 import java.io.OutputStream;
  9 import java.io.PrintWriter;
 10 import java.util.zip.GZIPOutputStream;
 11 
 12 import javax.servlet.ServletException;
 13 import javax.servlet.http.HttpServlet;
 14 import javax.servlet.http.HttpServletRequest;
 15 import javax.servlet.http.HttpServletResponse;
 16 
 17 public class ServletDemo1 extends HttpServlet {
 18 
 19     public void destroy() {
 20         super.destroy(); 
 21         
 22     }
 23 
 24 
 25     public void doGet(HttpServletRequest request, HttpServletResponse response)
 26             throws ServletException, IOException {
 27          //把想测试的响应头代码放在doGet方法里  
 28     }
 29 
 30 
 31     /**
 32      * 让浏览器以什么方式打开数据,content-disposition
 33      * @param response
 34      * @throws IOException
 35      */
 36     private void test5(HttpServletResponse response) throws IOException {
 37         response.setHeader("content-disposition", "attachment;filename=duwenlei.png");
 38         
 39         InputStream in = this.getServletContext().getResourceAsStream("1.png");
 40         int len;
 41         byte[] buffer = new byte[1024];
 42         OutputStream out = response.getOutputStream();
 43         while((len = in.read(buffer)) > 0){
 44             out.write(buffer, 0, len);
 45         }
 46     }
 47 
 48 
 49     /**
 50      * 通过refresh头,来控制浏览器多长时间刷新一次
 51      * @param response
 52      * @throws IOException
 53      */
 54     private void test4(HttpServletResponse response) throws IOException {
 55         String data = "bbbbbbbbbbbbbbb";
 56         response.setHeader("refresh", "3");//3秒刷新一次
 57         // response.setHeader("refresh", "3;url='http://www.baidu.com'"); 三秒后跳转到百度,用于注册成功跳转首页效果
 58         response.getOutputStream().write(data.getBytes());
 59     }
 60 
 61 
 62     /**
 63      * 向网页写一张图片,通过Content-type告诉浏览器返回的数据类型
 64      * @param response
 65      * @throws IOException
 66      */
 67     private void test3(HttpServletResponse response) throws IOException {
 68         InputStream in = this.getServletContext().getResourceAsStream("1.png");
 69         int len;
 70         byte[] buffer = new byte[1024];
 71         //这个Content-Encoding 的类型在tomcat/conf/web.xml里存在,web.xml包含市面上
 72         //几乎所有的文件类型和对应的mime-type
 73         response.setHeader("Content-type", "image/png");
 74         OutputStream out = response.getOutputStream();
 75         while((len = in.read(buffer)) > 0){
 76             out.write(buffer, 0, len);
 77         }
 78     }
 79     
 80     /**
 81      * 利用状态码302,配合location实现重定向
 82      * @param response
 83      */
 84     public void test(HttpServletResponse response){
 85         response.setStatus(302);
 86         response.setHeader("location", "2.html");
 87     }
 88     
 89     /**
 90      * 通过Content-Encoding头和Content-Length,来实现浏览器识别gzip格式数据
 91      * 注意:这里的data的数据量要大一点,否则你会发现,数据一压反而大了
 92      * @param response
 93      * @throws Exception
 94      */
 95     public void test1(HttpServletResponse response) throws Exception{
 96         
 97         String data = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
 98         System.out.println("压缩前数据:" + data.getBytes().length + "字节");
 99         
100         //byteArray往内存里写
101         ByteArrayOutputStream bout = new ByteArrayOutputStream();
102         
103         //        (GZIPOutputStream)包装流————>写入————>底层流(bout)
104         GZIPOutputStream gout = new GZIPOutputStream(bout);
105         
106         gout.write(data.getBytes());
107         //这里有一个限制,包装流有一个缓冲,如果说你的数据没有放慢这个缓冲,
108         //那么包装流就写不进底层流。怎么解决呢,很简单,我们把包装流关闭
109         //他就可以写到底层流了
110         gout.close();
111         
112         byte[] gzip = bout.toByteArray();   //得到压缩数据
113         
114         System.out.println("压缩后数据:" + gzip.length + "字节");
115         
116         //通知浏览器数据采用的压缩格式
117         response.setHeader("Content-Encoding", "gzip");
118         
119         //这里还要通知浏览器数据的长度
120         response.setHeader("Content-Length", gzip.length+"");
121         
122         //response.getOutputStream(),拿到浏览器的一个输出流,把压缩后的数据输出
123         response.getOutputStream().write(gzip);
124         
125     }
126 
127 
128     public void doPost(HttpServletRequest request, HttpServletResponse response)
129             throws ServletException, IOException {
130     }
131 
132     
133     public void init() throws ServletException {
134         
135     }
136 
137 }

  这里有一个range头,用这个头来实现断点下载,我这里那出来单说,这个是Http请求头的字段,对于这个range头,你得要服务器支持才行

  tomcat5不支持,从tomcat6以后支持,所以,要检查下你的服务器支不支持。

  断点下载就是,如果浏览器下载一个文件,下载到一半,突然断网了,适用于这个情况,断网了,但是我们已经下载了一部分,当有网的时候,我们不可能在去重新的去下载这个文件,我们要接着继续下载这个文件以后的内容。

     range有三种格式来设置传输字节的范围

      1.range:bytes=1000-2000 传输从1000到2000字节

      2.range:bytes=1000-        传输web资源1000字节以后的所有内容

      3.range:bytes=1000    传输最后1000字节

  

 1 URL url = new URL("http://localhost:8080/day02/a.txt");
 2         //我们这里是http协议,所以我们要用HttpURLConnection
 3         HttpURLConnection conn = (HttpURLConnection) url.openConnection();
 4         //打开了连接我们要设置range请求头,我们这里假设已经往我的本地下载了5个字节
 5         //现在我们要下载5往后的数据
 6         conn.setRequestProperty("range", "bytes=5-");
 7         //拿到一个写入流
 8         InputStream in = conn.getInputStream();
 9         //这里要注意,我们之前已经下载了5个字节,现在要做的是在这5个字节后面追加
10         //查api我们知道FileOutputStream(url,boolean),后面这个参数是问你是否
11         //续写,默认是false,在这里改成打开
12         FileOutputStream out = new FileOutputStream("E:\b.txt",true);
13         
14         //模版方法
15         int len;
16         byte[] buffer = new byte[1024];
17         while((len = in.read(buffer)) > 0){
18             out.write(buffer, 0, len);
19         }
20         in.close();
21         out.close();

  ok,打完。 

如果有使用请标明来源:http://www.cnblogs.com/duwenlei/
原文地址:https://www.cnblogs.com/duwenlei/p/3479051.html