0%

Http协议浅析

一、基本网络相关概念

1,网络分层
分层为了将网络节点所要完成的数据的发送或转发、打包或拆包,以及控制信息的加载或拆出工作,分别由不同的硬件和模块来完成,这样分层的好处是可以可以将通信和网络互联这一原本复杂的问题简单化,网络分层有经典的七层网络和五层,一般来说五层协议更加常用,应用更广泛,因为它更好理解。网络分层的每一层都是为了完成某一种功能而设计的。为了实现这些功能就要遵守共同的规则,就是协议规则。


如上图所示,从上到下一次分为应用层、传输层、网络层、数据链路层和物理层。我们比较关心的是应用层和传输层,这两层与我们平时的开发相关性较大。著名的TCP协议就是处于传输层(包括不可靠通信协议UDP,TCP是可靠的);而Http、FTP、SMTP、POP3位于应用层。
2,TCP协议的三四握手与四次挥手
在分析OkHttp框架的时候会用到TCP的相关知识,通常我们进行HTTP连接的时候会进行TCP的三次握手,然后传输数据,之后再释放;连接。TCP传输如图所示:


三次握手和的过程详细如下:


三次握手过程

  • a,第一次握手,建立连接。客户端发送SYN包到服务器,其中包含客户端的初始序号seq=x,并进入SYN_SENT状态,等待服务器确认。(其中,SYN=1,ACK=0,表示这是一个TCP连接请求数据报文;序号seq=x,表明传输数据时的第一个数据字节的序号是x)。
  • b,第二次握手:服务器收到请求后,必须确认客户的数据包。同时自己也发送一个SYN包,即SYN+ACK包,此时服务器进入SYN_RECV状态。(其中确认报文段中,标识位SYN=1,ACK=1,表示这是一个TCP连接响应数据报文,并含服务端的初始序号seq(服务器)=y,以及服务器对客户端初始序号的确认号ack(服务器)=seq(客户端)+1=x+1)。
  • c,第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送一个序列号(seq=x+1),确认号为ack(客户端)=y+1,此包发送完毕,客户端和服务器进入ESTAB_LISHED(TCP连接成功)状态,完成三次握手。

    四次挥手过程

  • a,首先,客户端发送一个FIN,用来关闭客户端到服务器的数据传送,然后等待服务器的确认。其中终止标志位FIN=1,序列号seq=u,此时客户端进入FIN_WAIT_1状态,表示客户端没有数据要发送给服务端了。
  • b,服务器收到这个FIN,它发送一个ACK,确认ack为收到的序号加1。
  • c,服务端想客户端发送一个FIN给客户端,请求关闭连接,同时服务端进入LAST_ACK状态。
  • d,客户端收到FIN报文段后,发回一个ACK报文确认,并将确认序号seq设置为收到序号加1。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。客户端发送FIN后,进入终止等待状态,服务器收到客户端连接释放报文段后,就立即给客户端发送确认,服务器就进入CLOSE_WAIT状态,此时TCP服务器进程就通知高层应用进程,因而从客户端到服务器的连接就释放了。此时是“半关闭状态”,即客户端不可以发送给服务器,服务器可以发送给客户端。 此时,如果服务器没有数据报发送给客户端,其应用程序就通知TCP释放连接,然后发送给客户端连接释放数据报,并等待确认。客户端发送确认后,进入TIME_WAIT状态,但是此时TCP连接还没有释放,然后经过等待计时器设置的2MSL后,才进入到CLOSE状态。

如果有大量的连接,每次连接、关闭时都要经历三次握手、四次挥手,这显然很浪费资源造成性能下降。因此Http有一种keepalive-connections的机制,它可以在传输数据后仍然保持连接,当客户端需要再次获取数据时,直接使用刚刚空闲下来的连接而无需再次建立连接了。

TCP协议常见问题:

  • 为什么需要三次握手,两次不可以吗?或者四次、五次可以吗?
    我们来分析一种特殊情况,假设客户端请求建立连接,发给服务器SYN包等待服务器确认,服务器收到确认后,如果是两次握手,假设服务器给客户端在第二次握手时发送数据,数据从服务器发出,服务器认为连接已经建立,但在发送数据的过程中数据丢失,客户端认为连接没有建立,会进行重传。假设每次发送的数据一直在丢失,客户端一直SYN,服务器就会产生多个无效连接,占用资源,这个时候服务器可能会挂掉。这个现象就是我们听过的“SYN的洪水攻击”。总结:第三次握手是为了防止:如果客户端迟迟没有收到服务器返回确认报文,这时会放弃连接,重新启动一条连接请求,但问题是:服务器不知道客户端没有收到,所以他会收到两个连接,浪费连接开销。如果每次都是这样,就会浪费多个连接开销。
  • 为什么需要2MSL时间?
    首先,MSL即Maximum Segment Lifetime,就是最大报文生存时间,是任何报文在网络上的存在的最长时间,超过这个时间报文将被丢弃。《TCP/IP详解》中是这样描述的:MSL是任何报文段被丢弃前在网络内的最长时间。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒、1分钟、2分钟等。
  • 为什么是四次挥手,而不是三次或是五次、六次?
    双方关闭连接要经过双方都同意。所以,首先是客服端给服务器发送FIN,要求关闭连接,服务器收到后会发送一个ACK进行确认。服务器然后再发送一个FIN,客户端发送ACK确认,并进入TIME_WAIT状态。等待2MSL后自动关闭。

总结:
(1)为了保证客户端发送的最后一个ACK报文段能够到达服务器。即最后一个确认报文可能丢失,服务器会超时重传,然后服务器发送FIN请求关闭连接,客户端发送ACK确认。一个来回是两个报文生命周期。

如果没有等待时间,发送完确认报文段就立即释放连接的话,服务器就无法重传,因此也就收不到确认,就无法按步骤进入CLOSE状态,即必须收到确认才能close。
(2)防止已经失效的连接请求报文出现在连接中。经过2MSL,在这个连续持续的时间内,产生的所有报文段就可以都从网络消失。

二、Http协议原理

1,Http简介

Http是位于应用层协议,由于简介、快速的特性,广泛用于分布式超媒体信息系统。于1990年被提出,经过几年的发展,得到不断的完善。

HTTP的历史版本
  • HTTP0.9:1991年,只有一个GET命令,服务器只能回应HTML格式的字符串
  • HTTP1.0:1996年发布,内容增加很多,除了GET命令外,还增加了POST命令和HEAD命令。HTTP请求和响应的格式除了部分数据,每次通信都必须包括头信息,用来描述一些元数据
  • HTTP1.1:1997年发布,进一步完善了,现在还是最流行的版本。
  • SPDY:2009年谷歌为了解决Http1.1效率不高的问题而自行研究的协议
  • HTTP2:2015年新发布的协议,SPDY协议的主要特性也包含在里面
HTTP协议的主要特点
  • 支持C/S(客户端/服务端)模式
  • 简单快速:Client想Server请求服务时,只需要传输请求方法和路径。请求方法常用的有GET、HEAD、POST,每种方法都规定了客户端与服务端联系的类型的不同。由于HTTP协议简单,使得HTTP协议服务器的程序规模,因而通信速度快
  • 灵活:HTTP允许传输任意类型的对象,正在传输的类型由Content-Type加以标记,
  • 无连接:每次连接只处理一个请求,服务器处理完客户的请求,并收到客户的应答后,即断开连接,采用这种方式可以节省传输时间
  • 无状态:HTTP协议是无状态的,无状态是指协议对于事物处理没有记忆能力,缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大;而另一方面,在服务器不需要先前信息时它的应答速度就很快

HTTP URL协议格式:

1
http://host[":"port][abs_path]

协议各部分代表的意义

  • http:代表使用HTTP协议来访问服务器
  • host:表示合法的Internet主机域名或者ip地址
  • oort:表示指定一个端口号,为空则默认为80
  • abs_path:指请求资源的URI(web上任意的可用资源)
HTTP状态码
  • 200 请求成功
  • 301 资源被永久转移到其他URL
  • 404 请求的资源不存在
  • 500 内部服务器错误