Http请求 && TCP connection
来看一个生动的概念图:
从这个图中我们可以看到,user是我们用户,用户决定什么时候发起http请求,而http要发送数据给服务端,就会建立一个“通道”,或是说“传送带”(更形象)把数据传送过去。
那么这“传送带”就是所谓的TCP 连接(TCP connection)。我们在这里要谈论的三次握手就是tcp connection这里实现的。
TIPs:
- Http和tcp是完全不同的两个东西,他们都是相互独立的,只不过存在着合作的关系,http并不存在“连接”这个概念的,只有“请求”和“响应”这两个概念。
这就好比一个买家想要网购商品,那买家和卖家就是http的发起者,他们只有“下单”,“发货”两个概念。货物的运输是要交给货运公司的,这里的货运公司发送的方式就相当于我们的tcp协议。因此负责传输数据的则需要tcp出手,和http完全是两样东西。
- 不同Http的版本就可以选择不同tcp传输的细节。相当于可以通过http请求中设置某种参数,达到控制tcp传输的方式,但是需要注意,http控制的顶多是tcp什么时候开始,什么时候关闭,并不能控制tcp传输数据的传统套路,比如三次握手是无论如何都不能避免的。
按照上面形象的例子,买家和卖家都可以事先告诉送货公司,我的邮件送去之后,快递员应不应该马上离开,或者结束送货服务。买家和卖家只能要求快递员送货过程(http的版本特性,是送去了马上结束服务,还是不急着回来继续提供服务),而货运公司的传统业务惯例,如和接货方签字等必要的传统业务(三次握手)是不能受到买家和卖家的要求的。因此三次握手并非是http能控制的,我们只能选择tcp什么时候传,什么时候结束传递服务,和传递的货物是什么(不同的header,不同的主体等)
三次握手
为什么要有三次握手呢?
首先设想这样一个情况:
假如只有两次握手,那么当客户端发出连接请求后,服务端就像客户端发送消息说已经开启连接,但是我们都知道数据的传输最终是要走物理层的,光缆可能很长,网络传输中也会出现意外,如果服务端的告知数据在经过网络传输的过程中丢失了,或者存在了较大的延时,客户端是不知道的,也许客户端就会认为服务端没响应,从而触发了超时事件,关闭了连接,重新去进行别的连接请求去了。可是服务端并不知道客户端是否有接收到确认消息,依旧开放端口苦苦的等待客户端的确认收到资源的消息,浪费了资源。
或者说客户端第一次发送请求,但是由于网络传输的问题,请求的消息被延迟了,等客户端接收到请求消息时,客户端可能已经触发超时事件。如果只有两次握手,服务端在首次接收到消息就告知客户端,同时建立连接,可此时客户端由于已经等待超时,也就不会理睬服务端的消息,也就不会发送数据,服务端又会苦苦的开放端口进行等待。
如果存在三次握手,就可以完全的告知客户端和服务端双方的状态。
首先,客户端发出连接请求(一次),服务端就收到请求同时做出响应告知客户端(看看客户端到底能不能接收到数据),收到请求,如果你回应我,我就为你开放端口(两次),如果此时客户端做出了创建连接的响应(三次),那么服务端接收到消息后(此时已经确认客户端能收到数据)才会打开端口,然后客户端开始真正的发送数据发送。
补充一些常见的标志位:
-
SYN 建立连接
-
ACK 确认接受
-
FIN 结束连接
-
Seq 序列号,当发送一个数据的时候,数据被拆分成多个数据包来发送,序列号就是对每个数据包进行编号,这样接受方才能对数据包进行再次拼接。
关于三次握手和四次挥手比较好的博文: