从HTTP说起
互联网的通信都是遵循着一定的协议的,通信双方必须经过一些约定俗成的协议才能互相通信,不然我说中文,你说英文,两者相互听不懂对方的消息,这样是无法通信的,因此就必须约定双方都说中文或者英文,这样双方才能完美地进行通信。因此,互联网中一定得存在着各种各样的通信协议,才能相互的通信。
当我们使用浏览器访问某网站的时候,如当访问百度的时候,浏览器都会自动地在www.baidu.com前面加上http://这个东东,变成http://www.baidu.com,然后再去发起请求。http://这个东东就表明了我们的浏览器是以http协议去访问百度的服务器的。
那么是不是单单只有这种协议呢,不,完成不同的需求就需要不同的协议,比如上述的网页访问用到了HTTP协议,还有为提供可靠且有效的电子邮件传输而定义的SMTP协议、基于文件的传输而定义了FTP协议等等,这些协议都是应用层级别的协议,在计算机网络中,为了降低耦合度,类似函数之间的方法调用,采用了协议栈的概念,有OSI七层协议体系结构,也有TCP/IP四层协议体系结构,我们经常采用的是综合两者的有点,定义了一种只有五层协议的体系结构。传输层、网络层、数据链路层的协议都是通过操作系统内核去处理的,而应用层通过调用这些操作系统内核的代码去实现的,因此,可以说应用层的协议是基于下面的协议而实现的。
因此浏览器访问服务器的过程就可以抽象为如下图,这也是http协议的基本工作方式。客户进程(浏览器)的位置在最高的应用层,它向服务器主机的应用层服务器进程发出请求,请求建立连接,然后,服务器进程接受客户进程发来的请求。http只是一个应用层级别的协议,其实HTTP协议又是基于TCP协议的,TCP协议是传输层的东西。
因此,更具体一点,所有的这些通信,实际上都需要使用下面各层所提供的服务,可以表现为下图。
可以看出HTTP协议定义了通信的双方通信前必须要建立好连接,HTTP协议又是通过TCP协议去实现的,因此,HTTP中连接的建立、数据传送和连接的释放实则是由HTTP的底下运输层中的TCP协议去实现的。HTTP协议只是在TCP协议的基础上定义了一些属于自己的东西。
TCP的连接建立
因为TCP连接是可靠的连接,因此必须保障每一方都能够确知对方的存在,所以必须先经过建立连接的过程,使双方都在连接上,每一方都知道对方存在,才是保障可靠连接的前提。TCP建立连接的过程叫做握手,握手需要在客户与服务器之间交换三个TCP报文段,如下图为TCP建立连接的三次握手过程。
上图中客户端有CLOSED、SYN-SENT、ESTABLISHED三种状态,服务器有CLOSED、LISTEN、SYN-RCVD、ESTABLISHED四种状态。
CLOSED为关闭状态,是客户端与服务器端没有进行任何操作时候的状态,当服务器端开启监听端口的时候,服务器端变成LISTEN状态,监听和接收客户端的请求连接报文。
① 客户端发出打算建立TCP连接的请求报文,报文首部中的SYN位=1,说明该报文不能携带数据,但是要消耗一个序号(seq)。TCP是面向字节流的,在一个TCP连接中传送的字节流中的每一个字节都按顺序编号,该编号即为序号(seq)。该请求建立连接报文中选择一个初始序号seq=x,但是不携带数据。此时,TCP客户端进程进入SYN-SENT(同步已发送)状态。
② 服务端监听端口接收到请求后,如同意建立连接,则向客户端发送确认。在确认报文段中将SYN位和ACK位都置为1,SYN位=1说明该报文不携带数据,但同样也要消耗掉一个序号和选择一个初始序号seq=y。ACK位=1说明该报文中的确认号有效,确认号是ack=x+1,表示希望客户端传输的下一个序号为x+1(因为客户端在第一步已经发了一个序号为x的报文)。此时TCP服务器进程进入SYN-RCVD(同步收到)状态。
③ 客户端收到服务器的确认后,还要给服务器发出确认,故先将该确认报文段的ACK置为1,确认号ack=y+1,表示希望服务器端传输的下一个序号为y+1(因为服务器在上一步中已经发了一个序号为y的报文),而自己的序号为seq=x+1。此时,TCP连接已经建立,双方都进入ESTABLISHED(已建立连接)状态。
还不明白?我们用通俗的话再来描述以上的三次握手过程!
① 客户端:服务器,我们可以建立连接吗?
② 服务器:可以啊,我们建立连接吧!
③ 客户端:收到,建立连接吧!
然后建立TCP连接成功
如果是四次握手的话,就变成了如下
① 客户端:服务器,我们可以建立连接吗?
② 服务器:可以啊,我们建立连接吧!
③ 客户端:收到,我们建立连接吧!
④ 服务器:收到,我们建立连接吧!
然后建立TCP连接成功
服务器在②中都已经答应建立连接了,就不用再答应建立连接了,因此第4次握手是没有必要的。
那为什么不来2次握手呢?
① 客户端:服务器,我们可以建立连接吗?
② 服务器:可以啊,我们建立连接吧!
第一个原因:
两次握手中,客户端知道了服务器具有接收信息和发送信息的能力,但是服务器只知道客户端具有发送信息的能力,但是并不知道客户端具有接收信息的能力,如果加上第3次握手,服务器就知道了客户端具有接收信息的能力(因为客户端接收到了信息并且回复给服务器端)。
第二个原因:
现在考虑这么一种情况,由于网络拥堵,客户端发出的第一个连接请求报文段(第一次握手)在某些网络节点长时间滞留了,需要一些时间才能到达服务器。
然后由于客户端没有收到服务器的确认报文,客户端就认为这个连接请求报文段(第一次握手)失效了,于是重新发送这个连接请求报文,这一次没有因为网络堵塞而滞留在网络中,成功发送到服务器端了,因为是两次握手,所以两次握手后,连接就成功建立了。
客户端认为刚开始的那个由于网络拥堵而滞留在网络中的请求连接报文失效了,其实并没有失效,只是由于网络的拥堵而滞留在网络中而已,此时,网络不阻塞了,又畅通了,该报文成功到达了服务器,服务器又以为客户端要进行与服务器TCP的连接,于是服务器就又对这个连接请求报文进行应答,同意建立连接。假定不采用第三次握手,那么只要服务器发出确认,新的连接就建立了。
由于现在客户端并没有发出建立连接的请求,因此不会理睬服务器端的确认,也不会向服务器端发送数据。但服务器端却以为新的运输连接已经建立了,并一直等待客户端发来数据。服务器端的许多资源就这样白白浪费了。
因此,需要第三次握手来解决该问题,第三次握手是客户端发给服务器端的确认报文,如果服务器端过了规定的时间都没收到客户端的回复确认报文,于是也不会为客户端分配资源,因此,此次的连接就放弃啦,也不会耗费服务器端的资源了。
全文完