ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# HTTP协议入门——1.1版本 ### 基本概述     超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。所有的WWW文件都必须遵守这个标准。     HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传输协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。     HTTP是客户端浏览器或其他程序与Web服务器之间的应用层通信协议。在Internet上的Web服务器上存放的都是超文本信息,客户机需要通过HTTP协议传输所要访问的超文本信息。HTTP包含命令和传输信息,不仅可用于Web访问,也可以用于其他因特网/内联网应用系统之间的通信,从而实现各类应用资源超媒体访问的集成。   ### 长连接和短连接的区别 解释1 所谓长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差,    所谓短连接指建立SOCKET连接后发送后接收完数据后马上断开连接,一般银行都使用短连接 解释2 长连接就是指在基于tcp的通讯中,一直保持连接,不管当前是否发送或者接收数据。    而短连接就是只有在有数据传输的时候才进行连接,客户-服务器通信/传输数据完毕就关闭连接。 解释3 长连接和短连接这个概念好像只有移动的CMPP协议中提到了,其他的地方没有看到过。    通信方式    各网元之间共有两种连接方式:长连接和短连接。所谓长连接,指在一个TCP连接上可以连续发送多个数据包,在TCP连接保持期间,如果没有数据包发送,需要双方发检测包以维持此连接。短连接是指通信双方有数据交互时,就建立一个TCP连接,数据发送完成后,则断开此TCP连接,即每次TCP连接只完成一对 CMPP消息的发送。    现阶段,要求ISMG之间必须采用长连接的通信方式,建议SP与ISMG之间采用长连接的通信方式。 解释4 短连接:比如http的,只是连接、请求、关闭,过程时间较短,服务器若是一段时间内没有收到请求即可关闭连接。    长连接:有些服务需要长时间连接到服务器,比如CMPP,一般需要自己做在线维持。   参考文章:[http://blog.csdn.net/shine0181/article/details/7799754](http://blog.csdn.net/shine0181/article/details/7799754)   ### HTTP请求部分 #### 基本结构 GET /q547550831?viewmode=contents HTTP/1.1 [请求行] Host: blog.csdn.net [消息头] 消息名:内容 Connection: keep-alive  Cache-Control: max-age=0  Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8  User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36  Referer: http://blog.csdn.net/q547550831?viewmode=contents  Accept-Encoding: gzip, deflate, sdch  Accept-Language: zh-CN,zh;q=0.8 PS:这是我博客主页的请求头,但是这并不代表每个网页的请求头都是这一样的。 #### 请求方式     请求方式有: POST,GET,HEAD,OPTIONS,DELETE,TRACE,PUT,CONNECT等 参考文档:[http://tools.jb51.net/table/http_request_method](http://tools.jb51.net/table/http_request_method) 常用的有:POST和GET #### 请求消息头 Host: blog.csdn.net [主机名] Connection: keep-alive [连接状态:保持连接] Cache-Control: max-age=0 [指定请求和响应遵循的缓存机制:查看是否有修改并选择更新否] Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 [可接受的格式] User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36 [浏览器内核] Referer: [http://blog.csdn.net/q547550831?viewmode=contents](http://blog.csdn.net/q547550831?viewmode=contents) [从哪个网页跳转到这个网页来的,可以用来防盗链] Accept-Encoding: gzip, deflate, sdch [可接收的压缩格式] Accept-Language: zh-CN,zh;q=0.8 [浏览器支持的语言]   PS:请求是指浏览器发出向服务器发出,所以这些信息都是浏览器的信息。请求头远远不止这几种,可以参考该文档:[http://tools.jb51.net/table/http_header](http://tools.jb51.net/table/http_header)   案例:防止盗链 ~~~ package com.pc; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet6 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); out.println("<a href='http://127.0.0.1:8080/servlet1/Servlet5'>连接到Servlet5</a>"); out.flush(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } } ~~~ ~~~ package com.pc; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet5 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); PrintWriter out = response.getWriter(); // 通过request对象来获取http请求信息 // 取出Host String host = request.getHeader("Host"); out.println("host=" + host); // 限制用户 // 获取用户浏览器的Referer // referer可以防止盗链,通过判断链接来至哪里 String referer = request.getHeader("Referer"); if(referer == null || !referer.startsWith("http://127.0.0.1:8080/servlet1")){ out.println("非法盗链"); } else { out.println("referer=" + referer); } out.flush(); out.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 一般开发人员习惯把doGet()和doPost()合二为一 this.doGet(request, response); } public void init() throws ServletException { // Put your code here } } ~~~ PS:该案例中只能允许http://127.0.0.1:8080/servlet1开头的网址进行访问Servlet5 ### HTTP响应部分 #### 基本结构 HTTP/1.1 200 OK [状态行] Server: openresty [消息名] 消息名:内容 Date: Fri, 01 Jan 2016 08:11:04 GMT  Content-Type: text/html; charset=utf-8  Transfer-Encoding: chunked  Connection: keep-alive  Vary: Accept-Encoding  Cache-Control: private  Set-Cookie: uuid=5cad65d6-7a99-4b15-a6e6-5c50e584ca77; expires=Sat, 02-Jan-2016 08:13:49 GMT; path=/  Set-Cookie: ViewMode=contents; path=/  Content-Encoding: gzip **--------------这是一个空行** **消息体**   #### 响应状态码     响应状态码分别为1,2,3,4,5开头的三位数字 <table><tbody><tr><td valign="center"><p style="text-align:left">1**                       </p></td><td valign="center"><p style="text-align:left">信息,服务器收到请求,需要请求者继续执行操作</p></td></tr><tr><td valign="center"><p style="text-align:left">2**                      </p></td><td valign="center"><p style="text-align:left">成功,操作被成功接收并处理</p></td></tr><tr><td valign="center"><p style="text-align:left">3**                      </p></td><td valign="center"><p style="text-align:left">重定向,需要进一步的操作以完成请求</p></td></tr><tr><td valign="center"><p style="text-align:left">4**                      </p></td><td valign="center"><p style="text-align:left">客户端错误,请求包含语法错误或无法完成请求</p></td></tr><tr><td valign="center"><p style="text-align:left">5**                      </p></td><td valign="center"><p style="text-align:left">服务器错误,服务器在处理请求的过程中发生了错误</p></td></tr></tbody></table>   PS:常见的有200(成功),303(重定向),400(Not Found),500(服务器内部错误) 可以参考该文档:[http://tools.jb51.net/table/http_status_code](http://tools.jb51.net/table/http_status_code)   #### 响应消息头 Server: openresty [服务器名称] Date: Fri, 01 Jan 2016 08:11:04 GMT [原始服务器消息发出的时间] Content-Type: text/html; charset=utf-8 [返回内容的MIME类型] Transfer-Encoding: chunked [文件传输编码] Connection: keep-alive [连接状态:保持连接] Vary: Accept-Encoding [告诉下游代理是使用缓存响应还是从原始服务器请求] Cache-Control: private [告诉所有的缓存机制是否可以缓存及哪种类型] Set-Cookie: uuid=********; expires=Sat, 02-Jan-2016 08:13:49 GMT; path=/ [设置Http Cookie] Set-Cookie: ViewMode=contents; path=/ [设置Http Cookie] Content-Encoding: gzip [web服务器支持的返回内容压缩编码类型]   PS:可以参考该文档[http://tools.jb51.net/table/http_header](http://tools.jb51.net/table/http_header) ### 缓存机制     浏览器默认情况下,会缓存所访问的页面,这样会出现一个问题:如果用户习惯把光标停留在地址栏,然后回车来取页面,就会默认调用cache中取数据。   案例1、有些网站要求及时性很高,因此要求不缓存页面。 //指定该页面不缓存 Ie response.setDateHeader("Expires", -1);【针对IE浏览器设置不缓存】 //为了保证兼容性. response.setHeader("Cache-Control", "no-cache");【针对火狐浏览器等】 response.setHeader("Pragma", "no-cache");【其他浏览器】   案例2、有些网站要求网页缓存一定时间,比如缓存一个小时 response.setDateHeader("Expires", System.currentTimeMillis()+3600*1000); //后面一个参数表示设置的缓存保持时间,-1表示永远不缓存 ### Content-Type消息头     Content-Type,内容类型,一般是指网页中存在的Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件 PS:其作用就是告诉浏览器,该服务器返回的网页中消息体是什么格式的,该以什么编码格式来读取这个网页。 因为该类型很多,故给出参考文档,以备后用:[http://tools.jb51.net/table/http_content_type](http://tools.jb51.net/table/http_content_type) 案例1:定时刷新Refresh的使用  response.setHeader("Refresh", "5;url=/servletPro/Servlet2"); // 5秒后刷新并跳转到url后的链接。通过这个可以实现页面定时刷新。   案例2:文件下载 ~~~ package com.pc; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class Servlet7 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/html;charset=utf-8"); response.setCharacterEncoding("utf-8"); // 演示下载文件 response.setHeader("Content-Disposition", "attachment; filename=EVO_120G.jpg"); // 打开文件 // 1.获取到要下载文件的全路径 String path = this.getServletContext().getRealPath("/EVO_120G.jpg"); // 测试 System.out.println("path=" + path); // 2.创建文件输入流 FileInputStream fis = new FileInputStream(new File(path)); // 做一个缓冲字符数组 byte buff[] = new byte[1024]; int length = 0; // 3.指向response的输出流 OutputStream os = response.getOutputStream(); // 4.循环读出 // length表示每次实际读入的字节数 while((length = fis.read(buff)) != -1){ os.write(buff, 0, length); } // 关闭 os.close(); fis.close(); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doGet(request, response); } } ~~~   ----------参考《韩顺平.细说Servlet》