移动架构09-Http协议
HTTP(超文本传输协议)是一个应用层协议,基于TCP/IP通信协议来传递数据,默认端口号为80。Http由请求和响应构成,是一个标准的客户端服务器模型。Http请求是指Http格式的请求数据,Http响应是指Http格式的响应数据。
Http的特点是无连接,它限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。这样做是为了减小服务器的压力,节约资源。
一、网络分层
网络分层有3种分法:
- OSI七层模型:应 用层、表示层、会话 层、传输层、网 络层、数据链路层、物 理层
- TCP/IP五层模型:应 用层、传输层、网 络层、数据链路层、物 理层
- TCP/IP四层模型:应 用层、传输层、网 络层、物 理层
OSI七层模型:
- 应用层。用于文件传输、电子邮件、文件服务、虚拟终 端等,常用协议有 TFTP、HTTP、SNMP、FTP、SMTP、DNS、Telnet 。
- 表示层。用于数据格式化、代码转换、数据加密,没有协议 。
- 会话层。用于解除或建立与别的接点的联系,没有协议。
- 传输层。用于提供端对端的接口,常用协议有TCP、UDP (RTP)
- 网 络层。用于为数据包选择路由,常用协议有IP、ICMP、RIP、OSPF、BGP、IGMP
- 数据链路层。用于传输有地址的帧以及错误检测功能,常用协议有SLIP、CSLIP、PPP、ARP,RARP、MTU
- 物 理层。用于以二进制数据形式在物理媒体上传输数据,常用协议有ISO2110、IEEE802、IEEE802.2
二、TCP三次握手与四次挥手
TCP三次握手
- 第一次握手。服务端处于Listen状态,客户端发送请求连接报文,进入 SYN-SENT(同步已发送)状态。报文中SYN=1(代表请求连接,不携带数据),seq=x(代表初始序列号)。
- 第二次握手。服务端收到请求报文后,向客户端发送确认报文,进入SYN-RCVD(同步收到)状态。报文中ACK=1(代表确认报文),SYN=1,ack=x+1(代表确认号,客户端的序列号+1),seq=y(代表服务端的初始序列号)。
- 第三次握手。客户端收到服务端的确认报文后,向服务端也发送发送确认报文,进入ESTABLISHED(已建立连接)状态。报文中ACK=1,ack=y+1(代表确认号,服务端的序列号+1),seq=x+1(客户端的序列号+1)。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
![](https://img.haomeiwen.com/i11999223/c4b38b7b57bfa3e3.png)
为什么TCP客户端最后还要发送一次确认呢?
是为了防止服务器对失效的请求建立连接。比如,客户端第一次请求超时后,就会进行第二次请求,如果第二次请求成功后,服务器才接收到第一次请求。这个时候,如果没有3次握手,客户端和服务器就会再次连接,从而造成资料浪费和错误;如果进行第3次握手,客户端就不会发送确认报文,也就不会和服务器再次连接。
TCP四次挥手
- 第一次挥手。客户端进程发出请求关闭报文,并且停止发送数据,进入FIN-WAIT-1(终止等待1)状态。报文中FIN=1(代表确认报文,会携带数据),seq=u。
- 第二次挥手。服务器收到连接关闭报文后,发出确认报文,进入了CLOSE-WAIT(关闭等待)状态。报文中ACK=1,ack=u+1,seq=v。此时,客户端不再发送数据,服务端如果正在发送数据,就需要等待数据发送完。客户端收到服务器的确认请求后,进入FIN-WAIT-2(终止等待2)状态,等待服务器发送请求关闭报文。此时,服务端如果正在发送数据,客户端还需要接收数据。
- 第三次挥手。服务器停止发送数据,就向客户端发送请求关闭报文,进入了LAST-ACK(最后确认)状态等待客户端的确认。报文中FIN=1,ack=u+1。
- 第四次挥手。客户端收到服务器的连接关闭报文后,发出确认报文,进入了TIME-WAIT(时间等待)状态。报文中ACK=1,ack=w+1,seq=u+1。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。服务端接收到客户端发出的确认,立即关闭TCP连接,进入CLOSED状态。
![](https://img.haomeiwen.com/i11999223/fa119fd37120aeb4.png)
为什么客户端最后还要等待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协议:
![](https://img.haomeiwen.com/i11999223/19ee6dc029e0c5ce.png)
SSL协议工作流程:
![](https://img.haomeiwen.com/i11999223/679229ae5257175e.png)
四、Http请求与响应
Http请求由4部分组成:请求首行、请求头、请求空行、请求体(请求数据)
![](https://img.haomeiwen.com/i11999223/e519fae1d42f9e74.png)
Http响应由4部分组成:状态行、消息报头、空行和响应正文
![](https://img.haomeiwen.com/i11999223/ccca2b8bb14607a8.png)
五、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://www.jianshu.com/nb/25128604
喜欢请点赞,谢谢!
网友评论