IT老哥,一个在大厂做高级Java开发的程序员,每天分享技术干货文章
在我们日常工作中,无时无刻不在接触HTTP请求,那么HTTP又是基于TCP进行通信的,在面试中面试官经常会问我们,你知道三次握手
和四次挥手
吗,正在读这篇文章的你,知道吗?不知道的话就跟老哥来一起学习吧!!!
HTTP是应用层协议
。TCP是传输层协议
。HTTP是建立在TCP协议之上。,简单的说,TCP就是单纯建立连接,不涉及任何我们需要请求的实际数据,简单的传输。http是用来收发数据,即实际应用上来的。
客户端与服务器之间数据的发送和返回的过程当中需要创建一个叫TCP connection的东西;
由于TCP不存在连接的概念,只存在请求和响应,请求和响应都是数据包,它们之间都是经过由TCP创建的一个从客户端发起,服务器接收的类似连接的通道,这个连接可以一直保持,http请求是在这个连接的基础上发送的;
在一个TCP连接上是可以发送多个http请求的,不同的版本这个模式不一样。
HTTP/1.0:
这个TCP连接是在http请求创建的时候同步创建的,http请求发送到服务器端,服务器端响应了之后,这个TCP连接就关闭了;HTTP/1.1:
中可以以某种方式声明这个连接一直保持,一个请求传输完之后,另一个请求可以接着传输。这样的好处是:在创建一个TCP连接的过程中需要“三次握手”的消耗,“三次握手”代表有三次网络传输。如果TCP连接保持,第二个请求发送就没有这“三次握手”的消耗。HTTP/2
:中同一个TCP连接里还可以并发地传输http请求。Seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
Ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,Ack=Seq+1。
共6个,即URG、ACK、PSH、RST、SYN、FIN等,具体含义如下:
URG:
紧急指针(urgent pointer)有效。ACK:
确认序号有效。PSH:
接收方应该尽快将这个报文交给应用层。RST:
重置连接。SYN:
发起一个新连接。FIN:
释放一个连接。TCP链接建立的基础条件是存在一个客户端,一个服务端。
主动发起连接建立
的应用进程叫做客户
(client)。被动等待连接建立
的应用进程叫做服务器
(server)。
当客户端A想要访问服务器B上的服务,需要与B建立连接了,就要经历如下三次握手过程:
举个栗子:
把客户端比作男孩,服务器比作女孩。用他们的交往来说明“三次握手”过程:
(1)男孩喜欢女孩,于是写了一封信告诉女孩:我爱你,请和我交往吧!;写完信之后,男孩焦急地等待,因为不知道信能否顺利传达给女孩。
(2)女孩收到男孩的情书后,心花怒放,原来我们是两情相悦呀!于是给男孩写了一封回信:我收到你的情书了,也明白了你的心意,其实,我也喜欢你!我愿意和你交往!; 写完信之后,女孩也焦急地等待,因为不知道回信能否能顺利传达给男孩。
(3)男孩收到回信之后很开心,因为发出的情书女孩收到了,并且从回信中知道了女孩喜欢自己,并且愿意和自己交往。然后男孩又写了一封信告诉女孩:你的心意和信我都收到了,谢谢你,还有我爱你!
女孩收到男孩的回信之后,也很开心,因为发出的情书男孩收到了。由此男孩女孩双方都知道了彼此的心意,之后就快乐地交流起来了~~
客户端向服务端发送连接请求报文段。该报文段的头部中SYN=1,ACK=0,seq=x。请求发送后,客户端便进入SYN-SENT状态。
服务端收到连接请求报文段后,如果同意连接,则会发送一个应答:SYN=1,ACK=1,seq=y,ack=x+1。该应答发送完成后便进入SYN-RCVD状态。
SYN=1,ACK=1
表示该报文段为连接同意的应答报文。seq=y
表示服务端作为发送者时,发送字节流的初始序号。ack=x+1
表示服务端希望下一个数据报发送序号从x+1开始的字节。当客户端收到连接同意的应答后,还要向服务端发送一个确认报文段,表示:服务端发来的连接同意应答已经成功收到。
该报文段的头部为:ACK=1,seq=x+1,ack=y+1。客户端发完这个报文段后便进入ESTABLISHED状态,服务端收到这个应答后也进入ESTABLISHED状态,此时连接的建立完成
!
因为可能因为网络延迟等缘故,第一次握手时,在时间已经超时后客户端的syn才到服务器端;这个时候尽管客户端知道已经超时失效了,而服务器端还不知道,以为是刚刚发过来的,会回复一个ACK,统一建立连接。
如果不采用三次握手,则此时服务器端发出确认后,连接就正式建立,但是因为客户端并没有发出建立连接的请求,也就不会回应服务器端的ACK,也不会向服务器端发数据。所以服务器端就会一直处于等待状态,浪费了大量的资源。
采用三次握手后,由于服务器向客户端发了SYN后得不到确认,就知道客户端并没有要求建立连接。
所谓的四次挥手即TCP连接的释放(解除)。连接的释放必须是一方主动释放,另一方被动释放。以下为客户端主动发起释放连接的图解:
举个栗子:
把客户端比作男孩,服务器比作女孩。通过他们的分手来说明“四次挥手”过程。
"第一次挥手":
日久见人心,男孩发现女孩变成了自己讨厌的样子,忍无可忍,于是决定分手,随即写了第一封信
告诉女孩:我们分手吧。“第二次挥手”:
女孩收到信之后,知道了男孩要和自己分手,怒火中烧,心中暗骂:你算什么东西,当初你可不是这个样子的!于是立马给男孩回了一封回信
:分手就分手,给我点时间,我要把你的东西整理好,全部还给你!男孩收到女孩的第一封信之后,明白了女孩同意分手。随后等待女孩把自己的东西收拾好。
“第三次挥手”:
过了几天,女孩把男孩送的东西都整理好了,于是再次写信
给男孩:你的东西我整理好了,快把它们拿走,从此你我恩断义绝!“第四次挥手”:
男孩收到女孩第二封信之后,知道了女孩收拾好东西了,可以正式分手了,于是最后一次写信
告诉女孩:好,拜拜,祝你幸福!「进入正题」
若A认为数据发送完成,则它需要向B发送连接释放请求。该请求只有报文头,头中携带的主要参数为:
FIN=1,seq=u。此时,A将进入FIN-WAIT-1状态。
FIN=1
表示该报文段是一个连接释放请求。seq=u
,u-1是A向B发送的最后一个字节的序号。B收到连接释放请求后,会通知相应的应用程序,告诉它A向B这个方向的连接已经释放。此时B进入CLOSE-WAIT状态,并向A发送连接释放的应答,其报文头包含:ACK=1,seq=v,ack=u+1。
ACK=1:
除TCP连接请求报文段以外,TCP通信过程中所有数据报的ACK都为1,表示应答。seq=v
,v-1是B向A发送的最后一个字节的序号。ack=u+1
表示希望收到从第u+1个字节开始的报文段,并且已经成功接收了前u个字节。A收到该应答,进入FIN-WAIT-2状态,等待B发送连接释放请求。
第二次挥手完成后,A到B方向的连接已经释放,B不会再接收数据,A也不会再发送数据。但B到A方向的连接仍然存在,B可以继续向A发送数据。
当B向A发完所有数据后,向A发送连接释放请求,请求头:FIN=1,ACK=1,seq=w,ack=u+1。B便进入LAST-ACK状态。
A收到释放请求后,向B发送确认应答,此时A进入TIME-WAIT
状态。该状态会持续2MSL
时间,若该时间段内没有B的重发请求的话,就进入CLOSED状态,撤销TCB。当B收到确认应答后,也便进入CLOSED状态,撤销TCB。
「1」 因为Server端需要将数据给Client端发送完才可以断开连接,假如是三次挥手就可能出现数据还没有发送完就断开了连接,导致数据不完整。(Server端只向Client发送一次ACK确认信号的三次挥手情况)
「2」 Client有可能收不到Server发过来FIN信号(丢失),这时Server端已经断开连接,而Client由于没有收到FIN信号一直处于等待状态。(没有Client端向Server端发送的最后ACK确认信号的三次挥手情况)
因为要确保Server已经断开,Client才能断开。Server端可能没有收到Client端发来的最后确认信号ACK,如果这时Client端断开连接了,Server端就会一直等待下去。
TIME_WAIT
的大小一般为2MSL
(Maximum Segment Lifetime:报文最大生存时间),2MSL
也是数据包最大往返时间。
云服务器,云硬盘,数据库(包括MySQL、Redis、MongoDB、SQL Server),CDN流量包,短信流量包,cos资源包,消息队列ckafka,点播资源包,实时音视频套餐,网站管家(WAF),大禹BGP高防(包含高防包及高防IP),云解析,SSL证书,手游安全MTP,移动应用安全、 云直播等等。