基于TCP三次握手与四次挥手

TCP协议通讯下的窗口与滑动窗口的理解

    服务器客户端建立连接时,服务器与客户端都会分配一块缓冲区来接收数据,每进行一次数据交互,客户端都会将自己剩余的缓冲区尺寸发送到服务器,服务器在放回家收数据的确认信息中也将自己剩余的缓冲区尺寸发送到客户端。

    在TCP通讯中,剩余的缓冲区尺寸叫做窗口。

    TCP通讯过程的流程控制为:

    

    TCP主机对主机层的传输控制协议,分成6个标志位:

SYN(synchronous建立联机)

ACK(acknowledgement 确认)

PSH(push传送)

FIN(finish结束)

RST(reset重置)

URG(urgent紧急)

Sequence number(顺序号码)

Acknowledge number(确认号码)

    在客户端和服务器的TCP状态变化流程依次为:

客户端:CLOSED->SYN_SENT->ESTABLISHED->FIN_WAIT_1->FIN_WAIT_2->TIME_WAIT->CLOSED

服务器:CLOSED->LISTEN->SYN收到->ESTABLISHED->CLOSE_WAIT->LAST_ACK->CLOSED



    如上图所示,在TCP协议下,建立一个稳定的连接需要三次握手,分别为:


(1)第一次:客户端C在CLOSED未进行任何通讯的情况下,向服务器S发送SYN(j)数据包进行请求连接,发送完SYN数据包之后进入到SYN_SEND状态,该状态表示客户端的请求已发出,等待服务器确认。

(2)第二次:服务器确认收到客户端的SYN数据包,需要确认客户端是否真的是请求连接,将SYN(k)数据包和自己的确认信息ACK(j+1)数据包一起发给客户端,并进入到SYN_RECV 状态,为此次连接分配资源。该状态表示服务器已经接受到客户端的请求,等待客户端是否确认建立连接。

(3)第三次:处于SYN_SEND状态的客户端接收到服务器的SYN数据包和ACK(k+1)数据包,表示服务器已经接受到其请求,需要其对是否请求连接进行进一步确认。此时客户端发送确认建立连接的ACK数据包,并未此次连接分配资源。服务器收到ACK数据包以后,基于CTP的客户端与服务器的链接正式建立,双方进入到ESTABLISHED状态。表示连接已正式建立,可以进行数据的交互。

其中一方发送确认数据包的数值等于另一方发送数据的值+1

    TCP协议下,断开一个连接需要四次挥手:


(1)第一次:客户端C发送FIN报文,用来关闭客户端到服务器的数据发送,此时的客户端套接字并没有关闭,只是向服务器说明没有数据需要继续发送了。此时客户端进入到FIN_WAIT_1状态 ,等待服务器的对断开请求回应。

(2)第二次:服务器B收到这个FIN,返回一个ACK,确认序号为收到的序号加1。此时服务器处于CLOSE_WAIT状态,表示已经接受到客户端的断开请求,准备断开与此客户端的连接。 客户端收到服务器的ACK报文后,得知服务器正在处理自己的请求,断开与自己的连接,进入到FIN_WAIT_2状态。

(3)第三次:服务器断开与客户端的连接,断开完成后发送FIN报文到客户端,此时服务器进入LAST_ACK状态,表示连接已经断开成功。客户端收到FIN报文后,得知服务器与自己断开成功,发送一个断开成功的确认ACK报文,回收此次连接的所有资源,进入TIME_WAIT状态,等待一定的时间后CLOSE。

(4)第四次:服务器收到客户端发来的确认断开的ACK报文,回收此次连接的所有资源,然后关闭此次连接。


客户端与服务器在每次握手与挥手内容:


握手与挥手过程注意的问题:

1)在TIME_WAIT状态中,如果TCP client端最后一次发送的ACK丢失了,它将重新发送。TIME_WAIT状态中所需要的时间是依赖于实现方法的。典型的值为30秒、1分钟和2分钟。等待之后连接正式关闭,并且所有的资源(包括端口号)都被释放。

2)当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到Server端所有的报文都发送完了,才能发送FIN报文,因此不能一起发送。故需要四步握手。

3)TCP半连接:客户端在发送完SYN报文后,突然死机或者掉线,那么服务器发送的SYN和ACK报文客户端将收不到,因此客户端无法做出回应,服务器也会收不到客户端的ACK确认报文,这样的情况下服务器一般情况下会重新尝试,如果还未成功,者在一定时间后删除该客户端的请求。

    在此过程中,服务器处于SYN_RECV状态,称为半连接状态。半连接一般会保存在半连接队列中,在每收到ACK时会查找半连接队列,将建立连接成功的半连接从半连接队列中删除。大量的SYN_RECV的TCP连接将会导致半连接队列溢出,随后的连接请求将会被系统自动抛弃。

主动发起关闭连接的操作的一方将达到TIME_WAIT状态,而且这个状态要保持Maximum Segment Lifetime的两倍时间。为什么要这样做而不是直接进入CLOSED状态?

原因有二:
一、保证TCP协议的全双工连接能够可靠关闭
二、保证这次连接的重复数据段从网络中消失

先说第一点,如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

再说第二点,如果Client直接CLOSED,然后又再向Server发起一个新连接,我们不能保证这个新连接与刚关闭的连接的端口号是不同的。也就是说有可能新连接和老连接的端口号是相同的。一般来说不会发生什么问题,但是还是有特殊情况出现:假设新连接和已经关闭的老连接端口号是一样的,如果前一次连接的某些数据仍然滞留在网络中,这些延迟数据在建立新连接之后才到达Server,由于新连接和老连接的端口号是一样的,又因为TCP协议判断不同连接的依据是socket pair,于是,TCP协议就认为那个延迟的数据是属于新连接的,这样就和真正的新连接的数据包发生混淆了。所以TCP连接还要在TIME_WAIT状态等待2倍MSL,这样可以保证本次连接的所有数据都从网络中消失。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值