百味皆苦 java后端开发攻城狮

java复习HTTP协议

2019-03-17
百味皆苦

协议概念

  • HTTP 超文本传输协议 Hyper Text Transfer Protocol
  • 当我们在浏览器的地址栏输入一个地址的时候,就能够访问服务器的某个页面
  • 这个过程本身就是两个应用程序之间的交互,一个应用程序是浏览器,另一个应用程序是服务器。
  • 协议是什么? 协议就是不同的应用程序之间按照事先做好的约定进行的通信。 这样就能互相读懂对方的意思。
  • 浏览器和WEB服务器之间,使用的就是一种叫做HTTP的协议。 这样是BS (Browser Server )架构模型的基础
  • HTTP协议由请求和响应两种类型组成
  • HTTP 是基于 TCP/IP 协议通信协议来传递数据(HTML 文件、图片文件、查询结果等)。
  • 它不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认使用80端口。

协议特点

  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、PUT、DELETE、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  • 灵活:HTTP允许传输任意类型的数据对象。
  • 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  • 无状态HTTP协议是无状态的,HTTP 协议自身不对请求和响应之间的通信状态进行保存。任何两次请求之间都没有依赖关系。直观地说,就是每个请求都是独立的,与前面的请求和后面的请求都是没有直接联系的。协议本身并不保留之前一切的请求或 响应报文的信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的。

请求协议

  • 请求消息 由 请求行,请求头部,空行和请求数据4部分组成
  • 请求行:http://127.0.0.1/addHero.html提交的method是POST,访问的路径是addHero

空行

  • 最后一个请求头之后是一个空行,这个行非常重要,它表示请求头已经结束,接下来的是请求正文。

请求头

  • 请求头部信息提供了如下信息: Host: 主机名 User-Agent: 浏览器基本资料 Accept: 浏览器能够识别的响应类型 Accept-Language: 浏览器默认语言 Accept-Encoding: 浏览器能够识别的压缩方式 Referer: 来路页面, /addHero 这个路径是通过addHero.html这个页面跳转过来的。 Connecton:是否保持连接

请求数据

  • 点开Params页,可以看到本次提交数据所传递的参数

请求方法

  • GET:请求指定的页面信息,并返回实体主体。
  • HEAD:类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
  • POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。
  • PUT:从客户端向服务器传送的数据取代指定的文档的内容。
  • DELETE:请求服务器删除指定的页面。

Get—post

  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET请求会被浏览器主动缓存,而POST不会,除非手动设置。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST没有限制。
  • GET参数通过URL传递,POST放在Request body中。

响应协议

  • 响应信息由状态行,消息报头,响应正文组成
  • 访问页面可以看到响应代码是 200 OK,即表示响应成功

消息报头

  • 消息报头中提供如下信息: Content-Length: 表示长度 Content-Type: 内容格式 Date: 日期 Server: 服务器类型

响应正文

  • 在响应正文里就会是具体的html内容
  • 当然访问不同的页面,就不一定是html,有可能是css, js,甚至图片了。

响应代码

200

  • 200 表示响应成功了,比如打开页面, 就会看到200响应码

301

  • 301 表示客户端跳转,永久性的跳转
  • 为了实现301跳转,在Servlet中应该使用如下代码:
response.setStatus(301);
response.setHeader("Location", "fail.html");

302

  • 302 客户端跳转,临时性的跳转
  • 比如访问页面:http://127.0.0.1/addHero.html
  • 提交数据会访问addHero,addHero把数据加到数据库后,就会302跳转到listHero来显示新增加的Hero。
  • 在Servlet的代码实现要比301简单点,直接使用:response.sendRedirect("/listHero")

304

  • 304 表示资源未被修改。
  • 当不是第一次访问一个静态页面或者图片的时候,就会得到这么一个提示。
  • 这是服务端提示浏览器,这个资源没有发生改变,你直接使用上一次下载的就行了,不需要重新下载。
  • 这样就节约了带宽,并且浏览器的加载速度也更快。
  • 第二次访问页面就会看到304

404

  • 404表示访问的页面不存在
  • 比如访问页面http://127.0.0.1/addHero2.html
  • 这是一个不存在的页面,就会得到404响应码
  • 这表示一个浏览器的错误,就是服务端没提供这个服务,但是你却去访问。
  • 这个锅要算到浏览器头上,不能算在服务器头上。
  • 当然,有的时候是因为服务器没有配置这个路径,所以浏览器访问不到对应的资源。
  • 比如在web.xml中,没有配置listHero,就会得到404错误。

500

  • 500 表示服务端的错误
  • 比如增加新的英雄的时候,血量应该是一个数字,但是提交的数据是“100a”。
  • 而在服务端,使用Float.parseFloat() 试图把它转换为数字的时候,就会抛出异常。 这个就属于服务端的问题。

其他

  • 401:未授权
  • 402:需付费
  • 406:无法接受
  • 403:禁止访问
  • 404:无法找到
  • 405:方法不被允许
  • 408:请求超时
  • 409:指令冲突
  • 413:请求实体过大
  • 414:请求URL地址过长
  • 416:请求范围无法被满足
  • 417:预期内容错误
  • 426:需升级
  • 429:请求数过多
  • 431:请求头字段过大
  • 450:已被屏蔽
  • 500:服务器错误
  • 507:存量不足
  • 599:网络连接超时
  • 200:成功
  • 100:继续

持久连接

  • HTTP协议的初始版本中,每进行一次HTTP通信就要断开一次TCP连接
  • 每次的请求都会造成无谓的 TCP 连接建立和断开,增加通信量的 开销。
  • 为解决上述 TCP 连接的问题, HTTP/1.1 和一部分的 HTTP/1.0 想出了持久连接(HTTP Persistent Connections,也称为 HTTP keep-alive 或 HTTP connection reuse)的方法。持久连接的特点是,只要任意一端没有明确提出断开连接,则保持TCP连接状态。
  • 持久连接的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。另外, 减少开销的那部分时间,使 HTTP 请求和响应能够更早地结束,这样 Web 页面的显示速度也就相应提高了。
  • HTTP/1.1 中,所有的连接默认都是持久连接,但在 HTTP/1.0 内并未标准化。虽然有一部分服务器通过非 标准的手段实现了持久连接,但服务器端不一定能够支持持久连接。毫无疑问,除了服务器端,客户端也需 要支持持久连接。

管线化

  • 持久连接使得多数请求以管线化(pipelining)方式发送成为可能。
  • 从前发送请求后需等待并收到响应,才能 发送下一个请求。
  • 管线化技术出现后,不用等待响应亦可直接发送下一个请求。
  • 这样就能够做到同时并行发送多个请求,而不需要一个接一个地等待响应了。通俗地讲,请求打包一次传输过去,响应打包一次传递回来。管线化的前提是在持久连接下。
  • 假如当请求一个包含 10 张图片的 HTML Web 页面,与挨个连接相比,用持久连接可以让请求更快结束。 而管线化技术则比持久连接还要快
  • 于是在使用持久连接的情况下,某个连接上消息的传递类似于:
  • 请求1 -> 响应1 -> 请求2 -> 响应2 -> 请求3 -> 响应3
  • 管线化方式发送变成了类似这样:
  • 请求1 -> 请求2 -> 请求3 -> 响应1 -> 响应2 -> 响应3

c-t-s

  • cookie,token,session
  • Web应用中,HTTP请求是无状态的。即:用户第一次发起请求,与服务器建立连接并登录成功后,为了避免每次打开一个页面都需要登录一下,就出现了cookie,Session。
  • Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
  • Cookie存储的数据量有限,且都是保存在客户端浏览器中。
  • 不同的浏览器有不同的存储大小,但一般不超过4KB。
  • 因此使用Cookie实际上只能存储一小段的文本信息。
  • 例如:登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。
  • 这个时候用到的一个机制就是Cookie

session

  • Session是另一种记录客户状态的机制,它是在服务端保存的一个数据结构(主要存储的的SessionID和Session内容,同时也包含了很多自定义的内容如:用户基础信息、权限信息、用户机构信息、固定变量等)
  • 这个数据可以保存在集群、数据库、文件中,用于跟踪用户的状态。
  • 客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,这就是Session
  • 客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
  • 用户第一次登录后,浏览器会将用户信息发送给服务器,服务器会为该用户创建一个SessionId,并在响应内容(Cookie)中将该SessionId一并返回给浏览器,浏览器将这些数据保存在本地
  • 当用户再次发送请求时,浏览器会自动的把上次请求存储的Cookie数据自动的携带给服务器
  • 服务器接收到请求信息后,会通过浏览器请求的数据中的SessionId判断当前是哪个用户,然后根据SessionId在Session库中获取用户的Session数据返回给浏览器。
  • 如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份
  • Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了
  • session生成后,只要用户继续访问,服务器就会更新Session的最后访问时间,并维护该Session
  • 防止内存溢出,服务器会把长时间内没有活跃的Session从内存删除
  • 这个时间就是Session的超时时间。如果超过了超时时间没访问过服务器,Session就自动失效了

token

  • HTTP请求都是以无状态的形式对接
  • 即HTTP服务器不知道本次请求和上一次请求是否有关联
  • 所以就有了Session的引入,即服务端和客户端都保存一段文本,客户端每次发起请求都带着,这样服务器就知道客户端是否发起过请求。
  • 这样,就导致客户端频繁向服务端发出请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否
  • 而Session的存储是需要空间的,频繁的查询数据库给服务器造成很大的压力。
  • 在这种情况下,Token应用而生。
  • Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌
  • 当客户端第一次访问服务端,服务端会根据传过来的唯一标识userId,运用一些算法,并加上密钥,生成一个Token,然后通过BASE64编码一下之后将这个Token返回给客户端,客户端将Token保存起来(可以通过数据库或文件形式保存本地)。
  • 下次请求时,客户端只需要带上Token,服务器收到请求后,会用相同的算法和密钥去验证Token
  • 最简单的Token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由Token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接Token请求服务器)。
  • 使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录
  • 大概的流程是这样的:
  • 1)客户端使用用户名跟密码请求登录
  • 2)服务端收到请求,去验证用户名与密码
  • 3)验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
  • 4)客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者数据库里
  • 5)客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
  • 6)服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
  • APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为Token,存储到服务器中,并返回Token到APP
  • 以后APP请求时,凡是需要验证的地方都要带上该Token,然后服务器端验证Token,成功返回所需要的结果,失败返回错误信息,让他重新登录
  • 对于同一个APP同一个手机当前只有一个Token
  • 手机APP会存储一个当前有效的Token
  • 其中服务器上Token设置一个有效期,每次APP请求的时候都验证Token和有效期
  • 总结:
  • 『给我来份煎饼(token我是你对面摊卖烤冷面的,scope赊账)』『好』
  • 『鸡蛋(token我是你对面摊卖烤冷面的,scope赊账)』『好』
  • 『再加个鸡蛋(token我是你对面摊卖烤冷面的,scope赊账)』『好』
  • 最终得到一份普通煎饼,外加两个鸡蛋
  • 如果服务器重启或者因为其他理由,服务器端已保存token丢失。那么用户需 要重新登录和认证。
  • 『给我来份煎饼(token我是你对面摊卖烤冷面的)』『那个……我没见过你』

本篇文章参考自:http://how2j.cn


上一篇 java复习Tomcat

下一篇 java复习servlet

Comments

Content