三次握手
- 刚开始,客户端处于close状态,服务器端处于listen状态
- 第一次握手:客户端向服务器端发送SYN(请求同步)报文,并加上自己的初始序列号(客户端id)ISN(c),告诉对方自己是谁,此时客户端处于SYN_Send状态(发送状态).
- 第二次握手:服务器接收到客户端的SYN报文后,会向客户端发送自己的SYN报文,并加上自己的初始序列号(服务器端id)ISN(s),同时会把客户端的ISN(c)+1作为ACK(应答检验)的值,表示已经收到客户端的SYN,此时服务器处于SYN_Rcvd状态(中间状态,再进一步接收到客户端的ACK就进入建立状态).
- 第三次握手:客户端收到报文后,将ACK值-1检查ISN(c),确认无误后,会将服务器端的ISN(s)+1作为ACK的值发送给服务器端,表示已经收到服务器端的SYN,此时客户端处于establised状态(建立状态).
- 服务器端收到ACK后,将ACK值-1检查ISN(s),确认无误后,也处于establised状态(建立状态),此时双方建立连接.
为什么需要三次握手才能确定连接,两次不行?
握手连接要确定的问题是双方的发送能力和接收能力,四项都正常才能建立连接
第一次握手:客户端发送,服务器端接收.客户端可以确认:客户端的发送;服务器端可以确认:客户端的发送,服务器端的接收
第二次握手:服务器端发送,客户端接收.客户端可以确认:客户端的发送,接收,服务器端的发送,接收;服务器端可以确认:客户端的发送,服务器端的接收,发送
第三次握手:客户端发送,服务器端接收.客户端可以确认:客户端的发送,接收,服务器端的发送,接收;服务器端可以确认:客户端的发送,接收,服务器端的接收,发送
因此,需要三次才可以建立连接.
ISN是固定的吗?
如果ISN是固定的话,攻击者很容易猜出后续的确认号,因此ISN是动态生成的.
什么是半连接队列?
服务器在第一次接收客户端的SYN之后,就会处于SYN_RCVD状态.此时双方还没有完全建立起连接,这种状态下请求会被放在一个队列中,这个队列就是半连接队列,如果未收到客户端的回传,服务器端会进行重连,如果重连次数过多,会将请求从半连接队列中清除
举个简单一点的例子描述三次握手.甲乙两人在河的对岸,两人都想知道对方的信息然后开始交流,此时,甲先开始沟通
甲:你好(SYN),我是114(ISNc),能听到吗?(发送状态)
乙:你好(SYN),114(ACK),我是514(ISNs),能听到吗?(半连接状态)
甲:514(ACK),我听到了(建立状态)
经过这三次的沟通,甲乙两人就可以知道双方信息,并确定可以正常沟通了.
四次挥手
客户端和服务器端都可以主动发起断开连接请求,断开连接需要四次挥手,这里假设是客户端发起的断开请求.
第一次挥手:客户端向服务器端发送一份FIN(结束)包,客户端由establised(连接状态)变成结束等待1状态FIN-WAIT-1;
第二次挥手:服务器端接收到了FIN包,并会送一份ACK包,表示自己进入关闭等待状态CLOSE-WAIT,客户端进入结束等待2状态FIN-WAIT-2;服务端此时还可以发送未发送的数据,客户端此时还可以接收数据.
第三次挥手:待服务端发送完数据后,发送一份FIN包,进入最后确认状态LAST-ACK;
第四次挥手:客户端接收到服务器的报文后,会回送一份ACK包,进入超时等待状态TIME-WAIT,超时时间过后关闭连接CLOSED,而服务器端在接收完客户端传回的确认数据后立即关闭连接CLOSED
设置超时时间的原因?
假设客户端在发送完最后确认的ACK包后立即关闭连接,此时ACK在网络中丢失,服务器端将一直停留在LAST-ACK状态;如果客户端在发送完ACK包后等待一段时间,而服务器端没有收到,服务器端将会重新发送FIN包,客户端会响应新的FIN包,重发ACK包,并刷新超时时间.
四次挥手的过程好比你在周末的时候想回家喝妈妈煲的鸡汤,于是你打电话给妈妈(应答过程大概就是这样)
你:妈妈,我这个周末想回家喝鸡汤(这时候,你进入等待妈妈的回复)
妈妈:好的,我看看家里还有没有老母鸡(妈妈开始检查家里的存货,而你继续等待妈妈的回复)
妈妈:家里还有一只老母鸡,你快点回来吧(妈妈开始煲鸡汤)
你:好的,我马上回来(然后你开始先等一会,万一家里有什么事了,妈妈会打电话再次告诉你,暂时这个鸡汤煲不了了,让你再定一个时间,如果妈妈没有再打电话回来,那你就立马收拾东西回家了)
在四次挥手中的双方序号和确认号变化(感觉这块不是很重要)
因为在发送http请求和响应时序号和确实号被不断递增,因此这里就不用固定数字表示序号和确认号了,假设是x和y
第一次挥手时,客户端发送自己的序号和确认号给服务器端(客户端序号和确认号分别为x,y)
第二次挥手时,服务器端将客户端的确认号作为自己的序号,客户端的序号+1作为自己的确认号(服务器端序号和确认号分别为y,x+1)
第三次挥手时,因为没有进行一来一回的相互通信,所以序号和确认号没有变化(服务器端序号和确认号分别为y,x+1)
第四次挥手时,客户端将服务器端的确认号作为自己的序号,服务器端的序号+1作为自己的确认号(客户端序号和确认号分别为x+1,y+1)