Android开发Android开发经验谈

移动架构09-Http协议

2018-08-14  本文已影响9人  最爱的火

移动架构09-Http协议

HTTP(超文本传输协议)是一个应用层协议,基于TCP/IP通信协议来传递数据,默认端口号为80。Http由请求和响应构成,是一个标准的客户端服务器模型。Http请求是指Http格式的请求数据,Http响应是指Http格式的响应数据。

Http的特点是无连接,它限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。这样做是为了减小服务器的压力,节约资源。

一、网络分层

网络分层有3种分法:

  1. OSI七层模型:应 用层、表示层、会话 层、传输层、网 络层、数据链路层、物 理层
  2. TCP/IP五层模型:应 用层、传输层、网 络层、数据链路层、物 理层
  3. TCP/IP四层模型:应 用层、传输层、网 络层、物 理层

OSI七层模型:

  1. 应用层。用于文件传输、电子邮件、文件服务、虚拟终 端等,常用协议有 TFTP、HTTP、SNMP、FTP、SMTP、DNS、Telnet 。
  2. 表示层。用于数据格式化、代码转换、数据加密,没有协议 。
  3. 会话层。用于解除或建立与别的接点的联系,没有协议。
  4. 传输层。用于提供端对端的接口,常用协议有TCP、UDP (RTP)
  5. 网 络层。用于为数据包选择路由,常用协议有IP、ICMP、RIP、OSPF、BGP、IGMP
  6. 数据链路层。用于传输有地址的帧以及错误检测功能,常用协议有SLIP、CSLIP、PPP、ARP,RARP、MTU
  7. 物 理层。用于以二进制数据形式在物理媒体上传输数据,常用协议有ISO2110、IEEE802、IEEE802.2

二、TCP三次握手与四次挥手

TCP三次握手

  1. 第一次握手。服务端处于Listen状态,客户端发送请求连接报文,进入 SYN-SENT(同步已发送)状态。报文中SYN=1(代表请求连接,不携带数据),seq=x(代表初始序列号)。
  2. 第二次握手。服务端收到请求报文后,向客户端发送确认报文,进入SYN-RCVD(同步收到)状态。报文中ACK=1(代表确认报文),SYN=1,ack=x+1(代表确认号,客户端的序列号+1),seq=y(代表服务端的初始序列号)。
  3. 第三次握手。客户端收到服务端的确认报文后,向服务端也发送发送确认报文,进入ESTABLISHED(已建立连接)状态。报文中ACK=1,ack=y+1(代表确认号,服务端的序列号+1),seq=x+1(客户端的序列号+1)。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
Http协议-001

为什么TCP客户端最后还要发送一次确认呢?

是为了防止服务器对失效的请求建立连接。比如,客户端第一次请求超时后,就会进行第二次请求,如果第二次请求成功后,服务器才接收到第一次请求。这个时候,如果没有3次握手,客户端和服务器就会再次连接,从而造成资料浪费和错误;如果进行第3次握手,客户端就不会发送确认报文,也就不会和服务器再次连接。

TCP四次挥手

  1. 第一次挥手。客户端进程发出请求关闭报文,并且停止发送数据,进入FIN-WAIT-1(终止等待1)状态。报文中FIN=1(代表确认报文,会携带数据),seq=u。
  2. 第二次挥手。服务器收到连接关闭报文后,发出确认报文,进入了CLOSE-WAIT(关闭等待)状态。报文中ACK=1,ack=u+1,seq=v。此时,客户端不再发送数据,服务端如果正在发送数据,就需要等待数据发送完。客户端收到服务器的确认请求后,进入FIN-WAIT-2(终止等待2)状态,等待服务器发送请求关闭报文。此时,服务端如果正在发送数据,客户端还需要接收数据。
  3. 第三次挥手。服务器停止发送数据,就向客户端发送请求关闭报文,进入了LAST-ACK(最后确认)状态等待客户端的确认。报文中FIN=1,ack=u+1。
  4. 第四次挥手。客户端收到服务器的连接关闭报文后,发出确认报文,进入了TIME-WAIT(时间等待)状态。报文中ACK=1,ack=w+1,seq=u+1。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。服务端接收到客户端发出的确认,立即关闭TCP连接,进入CLOSED状态。
Http协议-002

为什么客户端最后还要等待2MSL?

是为了保证服务器正常关闭。因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

三、Http历史

1.Http1.0与1.1对比

Keep-Alive

HTTP1.0中,大多实现为每个请求/响应交换使用新的连接
HTTP1.1中,默认使用Keep-Alive,即请求头中包含一个Connection: Keep-Alive的键值对

缓存处理

HTTP1.0中主要使用header里的If-Modified-Since,Expires来做为缓存判断的标准;
HTTP1.1则引入了更多的缓存控制策略例如Entity tag,If-Unmodified-Since, If-Match, If-None-Match等更多可供选择的缓存头来控制缓存策略。

带宽优化及网络连接的使用
HTTP1.0中,存在一些浪费带宽的现象,例如客户端只是需要某个对象的一部分,而服务器却将整个对象送过来
了,并且不支持断点续传功能;
HTTP1.1则在请求头引入了range头域,它允许只请求资源的某个部分,即返回码是206。

错误通知的管理
HTTP1.1中新增了24个错误状态响应码,如409请求的资源与资源的当前状态发生冲突;410表示服务器上的某个资源被永久性的删除。

Host头处理
HTTP1.0中认为每台服务器都绑定一个唯一的IP地址,因此,请求消息中的URL并没有传递HOST。
其实目前在一台物理服务器上可以存在多个虚拟主机,并且它们共享一个IP地址;
HTTP1.1的请求消息和响应消息都应支持Host头域,且请求消息中如果没有Host头域会报告一个400 Bad Request错误。

2.Http2.0

HTTP 2.0是在SPDY(An experimental protocol for a faster web, The Chromium Projects)基础上形成的下一代互联网通信协议。HTTP/2 的目的是通过支持请求与响应的多路复用来较少延迟,通过压缩HTTPS首部字段将协议开销降低,同时增加请求优先级和服务器端推送的支持。

HTTP 1.x在应用层以纯文本的形式进行通信,而HTTP 2.0将所有的传输信息分割为更小的消息和帧,并对它们采用二进制格式编码。这样,客户端和服务端都需要引入新的二进制编码和解码的机制。

3.Https

Https即安全的Http。HTTP1.x在传输数据时,所有传输的内容都是明文,无法保证数据的安全性。Https传输的内容为密文。

Https协议:

Http协议-003

SSL协议工作流程:

Http协议-004

四、Http请求与响应

Http请求由4部分组成:请求首行、请求头、请求空行、请求体(请求数据)

Http协议-005

Http响应由4部分组成:状态行、消息报头、空行和响应正文

Http协议-006

五、Socket实现Http请求与Https请求

实现get请求:

Socket socket = new Socket("restapi.amap.com", 80);
//发送数据数据的输出流
BufferedWriter  bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//请求首行
bw.write("GET /v3/weather/weatherInfo?city=长沙&key=13cb58f5884f9749287abbead9c658f2 HTTP/1.1\r\n");
//请求头
bw.write("Host: restapi.amap.com\r\n");
//请求空行
bw.write("\r\n");
bw.flush();

实现Post请求:

Socket socket = new Socket("restapi.amap.com", 80);
//发送数据数据的输出流
BufferedWriter  bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
String data = URLEncoder.encode("city", "utf-8") + "=" + URLEncoder.encode("长沙", "utf-8") + "&" +URLEncoder.encode("key", "utf-8") + "=" + URLEncoder.encode("13cb58f5884f9749287abbead9c658f2", "utf-8");
//请求首行
bw.write("POST /v3/weather/weatherInfo HTTP/1.1\r\n");
//请求头
bw.write("Host: restapi.amap.com\r\n");
bw.write("Content-Length: " + data.length() + "\r\n");
bw.write("Content-Type: application/x-www-form-urlencoded\r\n");
//请求空行
bw.write("\r\n");
//请求体
bw.write(data);
bw.flush();

实现Https的get请求:

//使用SSLSocketFactory来创建Https的Socket,端口为443
Socket socket = SSLSocketFactory.getDefault().createSocket("www.baidu.com", 443);
//发送数据数据的输出流
BufferedWriter  bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
//请求首行
bw.write("GET /v3/weather/weatherInfo?city=长沙&key=13cb58f5884f9749287abbead9c658f2 HTTP/1.1\r\n");
//请求头
bw.write("Host: restapi.amap.com\r\n");
//请求空行
bw.write("\r\n");
bw.flush();

最后

代码地址:https://gitee.com/yanhuo2008/Common/blob/master/DemoHttp/src/main/java/gsw/demohttp/socket/ActivitySocket.java

移动架构专题:https://www.jianshu.com/nb/25128604

喜欢请点赞,谢谢!

上一篇 下一篇

猜你喜欢

热点阅读