一.HTTP简介
1、客户端连上web服务器后,若想获得web服务器中的某个web资源,需遵守一定的通讯格式,HTTP协议用于定义客户端与web服务器通迅的格式。
2、WEB浏览器与WEB服务器之间的一问一答的交互过程必须遵循一定的规则,这个规则就是HTTP协议。
3、HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议集中的一个应用层协议,用于定义WEB浏览器与WEB服务器之间交换数据的过程以及数据本身的格式。
4、HTTP协议的版本
HTTP/1.0、HTTP/1.1
HTTP/1.0和HTTP/1.1的区别:在HTTP1.0协议中,客户端与web服务器建立连接后,只能获得一个web资源。
HTTP1.1协议,允许客户端与web服务器建立连接后,在一个连接上获取多个web资源。
5、HTTP协议是学习JavaWEB开发的基石,不深入了解HTTP协议,就不能说掌握了WEB开发,更无法管理和维护一些复杂的WEB站点。深入理解HTTP协议,对管理和维护复杂的WEB站点、开发具有特殊用途的WEB服务器程序具有直接影响。
二、HTTP请求消息
1、客户端连上服务器后,向服务器请求某个web资源,称之为客户端向服务器发送了一个HTTP请求。一个完整的HTTP请求包括如下内容:一个请求行、若干消息头(若干请求头)、空行、请求数据.
eg.
GET /books/java.html HTTP/1.1————————请求行(请求行用于描述客户端的请求方式,请求的资源名称,以及使用使用的HTTP协议的版本号)
Accept: */*
Accept-Language: en-us
Connection: Keep-Alive
Host: localhost(客户机通过这个头,告诉服务器,想访问服务器哪台主机}——————多个消息头 (请求头用于描述客户端请求哪台主机,以及客户端的一些环境信息等)
Referer: http://localhost/links.asp(客户机通过这个头,告诉服务器,客户机是从哪个页面来的(防盗链)
User-Agent: Mozilla/4.0 (说明客户机操作系统信息,以及浏览器信息)
Accept-Encoding: gzip, deflate(客户机通过这个头,告诉服务器,支持哪种数据压缩格式)
———————————一个空行
请求数据---------------------------------(上网填写表单的时候)
2.
HTTP请求的细节——请求行
请求行中的GET称之为请求方式,请求方式有:
POST、GET、HEAD、OPTIONS、DELETE、TRACE、PUT
常用的有: GET、 POST
用户如没有设置,默认情况下浏览器向服务器发送的都是get请求,例如在浏览器直接输地址访问,点超链接访问等都是get,用户如想把请求方式改为post,可通过更改表单的提交方式实现。
eg.
1)改变客户端的请求方式
<form action="/1.html" method="post">
<input type="text" name="username"><input type="submit value="提交">
</form>
2)
<a href="/2.html?username=zhangsan>点击</a> <!--在用户点击这个超链接的时候带一点数据给服务器-->
不管POST或GET,都用于向服务器请求某个WEB资源,这两种方式的区别主要表现在数据传递上:
如请求方式为GET方式,则可以在请求的URL地址后以?的形式带上交给服务器的数据,多个数据之间以&进行分隔,例如:
GET /mail/1.html?name=abc&password=xyz HTTP/1.1
GET方式的特点:在URL地址后附带的参数是有限制的,其数据容量通常不能超过1K。
如请求方式为POST方式,则可以在请求的实体内容中向服务器发送数据,Post方式的特点:传送的数据量无限制。
3.HTTP请求细节——消息头(请求头)
用于HTTP请求中的常用请求头:
1)Accept:text/html,image/*:用于告诉服务器,客户机支持的数据类型
2)Accept-Charset:ISO-8859-1:用于告诉服务器客户机采用的编码
3)Accept-Encoding:gzip,compress:用于告诉服务器客户机支持的数据压缩格式
4)Accept-Language: en-us,zh-cn :客户机的语言环境
5)Host: www.it315.org:80:告诉服务器要访问的主机名
6)If-Modified-Since:Tue, 11 Jul 2000 1412:31 GMT:客户机通过这个头告诉服务器,资源的缓存时间
7)Referer:http://www.it315.org/index.jsp:客户机通过这个头告诉服务器,它是从哪个资源来访问服务器的(用于防盗链)
8)Cookie:客户机通过这个头可以向服务器带数据
9)User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0):用户的操作系统情况(软件环境)
10)Connection: close/Keep-Alive :告诉服务器完成这次请求之后,和服务器是否保持连接
11)Date: Tue, 11 Jul 2000 18:23:51 GMT
三、HTTP响应
1、一个HTTP响应代表服务器向客户端回送的数据,它包括:
一个状态行、若干消息头、空行、以及实体内容 。
2、举例:
HTTP/1.1 200 OK————————————————状态行(状态行用于描述服务器对请求的处理结果)
Server: Microsoft-IIS/5.0 }
Date: Thu, 13 Jul 2000 05:46:53 GMT }——————多个响应头(响应头用来描述服务器的基本信息,以及数据的描述,
服务器通过这些数据的描述信息,可以通知客户端如何处理等一会它回送的信息)
Content-Length: 2291 Content-Type: text/html(服务器通过这个头告诉浏览器,回送的数据的大小) }
Cache-control: private }
——————————————————————一个空行
<HTML> }
<BODY> }————实体内容(代表服务器向客户端回送的数据)
……
3.HTTP响应的细节——状态行
1)、状态行
格式: HTTP版本号 状态码 原因叙述<CRLF>
举例:HTTP/1.1 200 OK
2)状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数,响应状态码分为5类,如下
状态码 | 含义 |
100~199 | 表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程 |
200~299 | 表示成功接收请求并已经完成整个处理过程,常用200 |
300~399 | 为完成请求,客户端需要进一步细化请求,例如:请求的资源已经移动一个新的地址,常用302 (情景如:你向我借钱,我说我没有,我要你去找别人借。常与location响应头一起使用,location指向那个地址,就去哪里找)、307和304(表示客户机缓存的版本是最新的,客户机应该继续使用它) |
400~499 | 客户端的请求有错误,常用404(服务器上不存在客户机所请求的资源,此时我们的地址写错了);403(此时数据资源存在,客户端没有访问权限,服务器拒绝服务) |
500~599 | 服务器端出现错误,常用500(服务器在处理资源是出现错误,服务器端里面写的程序如CGI、ASP、JSP等程序发生错误) |
4.HTTP响应细节——常用响应头
1)HTTP请求中的常用响应头:
Location:这个头配合302状态码使用,用于告诉客户找谁
Server:服务器通过这个头,告诉浏览器服务器的类型。
Content-Encoding:服务器通过这个头,告诉浏览器数据的压缩格式
Content-Length:压缩数据的长度
Content-Language:数据回送的语言环境
Content-Type:服务器通过这个头,告诉浏览器数据回送数据的类型
Last-Modified:服务器通过这个头,告诉浏览器当前资源缓存时间
Refresh:服务器通过这个头,告诉浏览器多长时间刷新一次
Content-Disposition:服务器通过这个头,告诉浏览器以下载的方式打开数据
Transter-Encoding:chunket:服务器通过这个头告诉浏览器数据的传送格式(一块块传送的)
ETag:缓存相关的头(每个web资源都会生成一个串即标示符,服务器给客户机,之后客户机再访问该资源,就会用这个标示符与服务器相比较,若一样就那缓存,否则客户
机就再次请求该资源。若果客户机刚刚访问完服务器,而此时服务器资源更新,这段时间很短如500ms,此时客户机就会那缓存而不会再次请求)
Expires:服务器通过这个头,告诉浏览器吧回送的资源缓存多长时间,0或-1表示不缓存数据
Cache-Contorl:no:cache
Pragma:no-cache
服务器通过以上两个头,也是控制浏览器不要缓存数据
有关上面响应头的示例代码:
package cn.guoqing.web.servlet;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.zip.GZIPOutputStream;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class ServletDemo1 extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
}
//服务器告诉浏览器返回的数据以下载的方式查看
private void test5(HttpServletResponse response) throws IOException {
response.setHeader("content-disposition", "attachment;filename=7.jpg");
InputStream in=this.getServletContext().getResourceAsStream("/7.jpg");
OutputStream out=response.getOutputStream();
byte[] buf=new byte[1024];
int length=0;
while((length=in.read(buf))!=-1){
out.write(buf, 0, length);
}
}
//在指定的时间后自动刷新浏览器端页面(此例转接到新浪首页)
private void test4(HttpServletResponse response) throws IOException {
String data="ddkfdfkdfkf";
response.setHeader("refresh", "3;url='http://www.sina.com'");
response.getOutputStream().write(data.getBytes());
}
//通过Content-Type头字段,告诉浏览器以哪种格式打开服务器返回的数据
private void test3(HttpServletResponse response) throws IOException {
//数据具体的格式是哪种,可以在tomcat服务器中的config文件中的web.xml文件中查找
response.setHeader("Content-Type", "image/jpeg");
InputStream in=this.getServletContext().getResourceAsStream("/7.jpg");
OutputStream out=response.getOutputStream();
byte[] buf=new byte[1024];
int length=0;
while((length=in.read(buf))!=-1){
out.write(buf, 0, length);
}
}
//压缩数据输出
private void test2(HttpServletResponse response) throws IOException {
String data="jjjjjjjjjjjjkskskls很多很多看看大幅度地方 " +
"多发点多发点 多考虑房价大幅空间多考虑放宽到疯狂大家决定开发领导疯狂得分减肥的罚款等" +
"发看大幅度地方 多发点多发点 多考虑房价大幅空间多考虑放宽到疯狂大家决定开发领导疯狂得分减肥的看大幅" +
"度地方 多发点多发点 多考虑房价大幅空间多考虑放宽到疯狂大家决定开发领导疯狂得分减肥的看大幅度地方 多发点多发点" +
" 多考虑房价大幅空间多考虑放宽到疯狂大家决定开发领导疯狂得分减肥的看大幅度地方 多发点多发点 多考虑房价大幅空间" +
"多考虑放宽到疯狂大家决定开发领导疯狂得分减肥的看大幅度地方 多发点多发点 多考虑房价大幅空间多考虑放宽到疯狂大家决" +
"定开发领导疯狂得分减肥的看大幅度地方 多发点多发点 多考虑房价大幅空间多考虑放宽到疯狂大家决定开发领导疯狂得分" +
"减肥的看大幅度地方 多发点多发点 多考虑房价大幅空间多考虑放宽到疯狂大家决定开发领导疯狂得分减肥的达开发和" +
"反对娿dl;afdf;dfdkdfkaldfldld";
System.out.println("压缩前数据的的大小为:"+data.getBytes().length);
ByteArrayOutputStream bout=new ByteArrayOutputStream();
//zip包装流
GZIPOutputStream gout=new GZIPOutputStream(bout);
//将数据写到zip包装流中
gout.write(data.getBytes());
//将数据刷新到bout流中
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);
}
//用location和302实现请求“重定向”(实现页面的跳转,如,登陆页面登陆成功后的页面跳转)
public void test1(HttpServletResponse response){
response.setStatus(302);
response.setHeader("location", "/day04/1.html");
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request,response);
}
}
2)HTTP实用头字段:
Range头指示服务器只传输一部分web资源。这个头可以用来实现断点续传功能。Range字段可以通过三种格式设置要传输的字节的范围:
Range: bytes=1000-2000 (传输范围从1000-2000字节)
Range: bytes=1000- (传输web资源中的第1000个字节以后的所有内容)
Range: bytes=1000 (传输最后1000个字节)
3)HTTP响应消息头字段
Accept-Ranges:这个字段说明web服务器是否支持Range,支持则返回Accept-Ranges:bytes,否则返回Accept-Ranges:none.
Content-Range:指定了返回的web资源的字节范围。这个字段值的格式:Content-Range:1000-3000/5000 ----->返回1000到3000个字节,整个资源的大小为5000个字节。
先关示意文件:
package cn.guoqing.ie;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class RangeDemo1 {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
rangeMethod();
}
//向服务器资源发送从一个文件中的指定到的位置处下载资源
private static void rangeMethod() throws MalformedURLException,
IOException, FileNotFoundException {
URL url=new URL("http://localhost:8080/day05/a.txt");
HttpURLConnection connection=(HttpURLConnection) url.openConnection();
connection.setRequestProperty("Range", "bytes=5-");
FileOutputStream fos=new FileOutputStream("c://a.txt",true);
byte[] b=new byte[1024];
int len=0;
InputStream in=connection.getInputStream();
while((len=in.read(b))!=-1){
fos.write(b, 0, len);
}
fos.close();
in.close();
System.out.println("断点下载完成!!");
}
}