TCP/I三次握手四次挥手

  • Post author:
  • Post category:其他


最初两端都是CLOSED状态,A主动打开连接,而B被控打开连接

A、B关闭状态CLOSED—-B收听状态LISTEN—-A同步已发送状态SYN-SEND—-B同步收到状态SYN-RCVD—-A、B连接已建立状态ESTABLISHED

B的TCP服务器进程先创建控制块TCB,准备接受客户进程的连接请求。然后服务器进入LISTEN状态,等待客户端的连接请求。

第一次握手:A的TCP客户进进程也是首先创建传输控制块TCB,然后向B发出连接,SYN=1(不允许携带数据,会消耗一个序号),seq=x(x是随机生成的),A进入SYN_SEND状态

第二次握手:B收到请求报文后,回送报文,SYN=1,ACK=1(可以携带数据,不携带数据不会消耗序号),seq=y(y是随机生成的),ack=x+1,B进入SYN_RCVD状态

第三次握手:A收到B的确认后,回送报文,ACK=1,seq=x+1,ack=y+1,A进入ESTABLISHED。当B收到A的确认后,也进入ESTABLISHED状态

为什么A要发送一次确认呢?可以二次握手吗?

主要是为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。如A发出连接请求。如A发出连接请求,但是连接请求报文丢失服务器未收到。于是A再重传一次连接请求,后来收到确认,建立了连接。数据传输完毕后,就释放了连接,A共发出了两次请求报文段,其中一个丢失,第二个到达B,但是第一个丢失的报文段只是在某些网络节点长时间滞留了,延误到释放连接后的某个时间才到达B,此时B误认为A又发出一次新的连接请求,于是就向A发出确认报文段,同意建立连接,如果不采用三次握手,只要B发出确认,就建立新的连接了,如果此时A不理睬B的确认且不发送数据,B就会一直等待A发送数据,浪费资源。

Server端易收到SYN攻击?

服务器端的资源分配是在第二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到SYN洪水攻击,SYN攻击就客户端在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待客户端确认,由于源地址不存在,因此Server需要不断重发直至超时,这些伪造的SYN包将长时间占用未连接队列,导致正常的SYN请求因为队列慢而被丢弃,从而引起网络拥塞甚至系统瘫痪。

防范SYN攻击措施:降低主机的等待时间使主机尽快的释放半连接的占用,短时间收到某IP的重复SYN则丢弃后续请求。

期初A和B处于ESTABLISHED状态—-A发出连接释放报文段并处于FIN-WAIT-1状态—-B发出确认报文段进入CLOSE-WAIT状态—-A收到确认后,进入FIN-WAIT-2状态并等待B的连接释放报文—-B没有数据要向A发送的数据,B发出连接释放报文段切进入LAST-ACK状态—-A发出确认报文段进入TIME-WAIT状态—-B收到确认报文段后进入CLOSED状态—-A经过等待计时器时间2MSL后,进入CLOSED状态。

A的应用进程先向TCP发送释放报文,FIN=1,seq=u,并停止再发送数据,主动关闭TCP连接,进入FIN-WAIT-1(终止等待1)状态,等待B的确认

B收到连接释放报文段后即发出确认报文段,ACK=1,seq=v,ack=u+1,B进入CLOSE-WAIT(关闭状态)状态,此时的TCP处于半关闭状态,A到B的连接释放

A收到B的确认后,进入FIN-WAIT-2(终止等待2)状态,等待B发出连接释放报文段

B没有数据向A发送了,B发出连接释放报文段FIN=1,ACK=1,seq=w,ack=u+1,B进入LAST_ACK(最后确认)状态,等待A的确认

A收到B的连接释放报文段后,回送确认报文 ACK=1,seq=u+1,ack=w+1,A进入TIME-WAIT(时间等待)状态。此时TCP连接为释放掉,需要经过时间等待计时器设置的时间2MSL后,A才进入CLOSED状态

为什么A在TIME-WAIT状态必须等待2MSL的时间?

MSL最大报文段寿命Maximum Segment Lifetime, MSL=2

1、保证A发送的最后一个ACK报文段能够到达B

2、防止“已失效的连接请求报文段”出现在本连接中

1)这个ACK报文段可能丢失,使得处于LAST-ACK状态的B收不到已发送的FIN+ACK报文段的确认,B超时重传FIN+ACK报文段,而A能在2MSL时间内收到这个重换的FIN+ACK报文段,接着A重传一次确认,重新启动2MSL计时器,最后A和B都进入到CLOSED状态,若A在TIME-WAIT状态不等待一段时间,而是发送完ACK报文段后立即释放连接,则无法收到B重传的FIN+ACK报文段,所以不会再发送一次确认报文,则B无法正常进入到CLOSED状态

2)A在发送完最后一个ACK报文段后,在经过2MSL,就可以使本连接持续的时间内所产生的所有报文都从网路中消失,使下一个新的连接中不会出现这种就旧的连接请求报文

为什么连接的时候是三次握手,关闭的时候却是四次握手?

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

为什么TIME_WAIT状态需要经过2MSL才能返回到CLOSED状态?

虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSED状态了,但是我们必须假想网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。



版权声明:本文为androidzsp原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。