TCP三次握手四次挥手--系列问题

1、三次握手四次挥手的具体过程

TCP三次握手四次挥手--系列问题
1、TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
2、TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这时报文首部中的同部位SYN=1,同时选择一个初始***seq=x,此时,TCP客户端进程进入了SYN-SENT(同步已发送状态)状态。
3、TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列seq=y,此时,TCP服务器进程进入了SYNRCVD(同步收到)状态。
4、TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的***seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。
5、当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

TCP三次握手四次挥手--系列问题
1、客户端进程发出连接释放报文:FIN=1,***为seq=u,并且停止发送数据。此时,客户端进入FIN-WAIT-1(终止等待1)状态。
2、服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的***seq=v,此时,服务端就进入了CLOSEWAIT(关闭等待)状态。此时TCP属于半关闭状态,客户端不能向服务端发送数据了,但服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3、客户端收到服务器的确认请求后,此时,客户端就进入FINWAIT-2(终止等待2)状态,等待服务器发送连接释放报文。
4、服务器将最后的数据发送完毕,向客户端发送连接释放报文,FIN=1,ack=u+1,假定***为seq=w,此时,服务器就进入LAST-ACK(最后确认)状态,等待客户端的确认。
5、客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,***是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,才进入CLOSED状态。
6、服务器只要收到了客户端发出的确认,立即进入CLOSED状态,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

2、为什么要进行第三次握手?(收到Server端的确认之后,Client还需要进行第三次“握手”呢?)

如果两次握手的话,客户端有可能因为网络阻塞等原因会发送多个请求报文,这时服务器就会建立连接,浪费掉许多服务器的资源。
采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,因而产生错误。
若client发出的第一个连接请求报文段并没有丢失,而是被阻塞了,以致延误到连接释放以后的某个时间才到达server。本来这是一个早已失效的报文段,但server收到此失效的连接请求报文段后,就误认为是client再次发出的一个新的连接请求。于是就向client发出确认报文段,同意建立连接。假设不采用“三次握手”,那么只要server发出确认,新的连接就建立了。由于现在client并没有发出建立连接的请求,因此不会理睬server的确认,也不会向server发送数据。但server却以为新的运输连接已经建立,并一直等待client发来数据。这样,server的很多资源就白白浪费掉了。

3、为什么要4次挥手?

确保数据能够完成传输。
建立连接的时候,服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以自己可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。
TCP是全双工模式,这就意味着,当主机1发出FIN报文段时,只是表示主机1已经没有数据要发送了,主机1告诉主机2,它的数据已经全部发送完毕了;但是,这个时候主机1还是可以接受来自主机2的数据;当主机2返回ACK报文段时,表示它已经知道主机1没有数据发送了,但是主机2还是可以发送数据到主机1的;当主机2也发送了FIN报文段时,这个时候就表示主机2也没有数据要发送了,就会告诉主机1,我也没有数据要发送了,之后彼此就会愉快的中断这次TCP连接。

4、为什么客户端最后还要等待2MSL?(time_wait状态产生的原因?)

MSL(MaximumSegmentLifetime,报文最大生存时间),TCP允许不同的实现可以设置不同的MSL值。客户端接收到服务器端的FIN报文后进入此状态,此时并不是直接进入CLOSED状态,还需要等待一个时间计时器设置的时间2MSL。这么做有两个理由:
1、保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失。
如果服务端没有收到客户端的确认报文段,那么就会重新发送连接释放请求报文段。而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文。
2、防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,等待2MSL时间,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

5、如果网络连接中出现大量TIME_WAIT状态带来的危害?

如果系统中有很多socket处于TIME_WAIT状态(TIME_WAIT状态一般维持在1-4分钟),当需要创建新的socket连接的时候可能会受到影响。如果很多连接快速的打开和关闭的话,系统中处于TIME_WAIT状态的socket将会积累很多,由于本地端口数量的限制(0-65535),同一时间只有有限数量的socket连接可以建立,如果太多的socket处于TIME_WAIT状态,客户端所在的操作系统的socket端口被用尽,系统无法再发起新的连接!

6、如何消除大量TCP短连接引发的TIME_WAIT?

1)可以改为长连接,但代价较大,长连接太多会导致服务器性能问题,而且PHP等脚本语言,需要通过proxy之类的软件才能实现长连接;
2)修改ipv4.ip_local_port_range,增大可用端口范围,但只能缓解问题,不能根本解决问题;3)客户端程序中设置socket的SO_LINGER选项;
4)客户端机器打开tcp_tw_recycle和tcp_timestamps选项;
5)客户端机器打开tcp_tw_reuse和tcp_timestamps选项;
6)客户端机器设置tcp_max_tw_buckets为一个很小的值

7、当关闭连接时最后一个ACK丢失怎么办?

如果最后一个ACK丢失的话,TCP服务器就会认为它的FIN丢失,进行重发FIN。在客户端收到FIN后,就会设置一个2MSL计时器,2MSL计时器可以使客户等待足够长的时间,使得在ACK丢失的情况下,可以等到下一个FIN的到来。如果在TIME-WAIT状态汇总有一个新的FIN到达了,客户就会发送一个新的ACK,并重新设置2MSL计时器。
如果重传FIN到达客户端时,客户端已经进入CLOSED状态时,那么客户就永远收不到这个重传的FIN报文段,服务器收不到ACK,服务器无法关闭连接。
但是服务器并不会一直无法关闭,服务器会进行不断的探查,会发送十个间隔为75秒的探查,如果探查都没有收到回应,则认为客户端已经关闭,服务器也将关闭,终止链接。

8、TCP三次握手有哪些漏洞?

(1)SYNFlood攻击
SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server则回复确认包,并等待Client确认,由于源地址不存在,因此Server需要不断重发(默认重发5次)直至超时,这些伪造的SYN包将长时间占用未连接队列和消耗CPU时间和内存,导致正常的SYN请求无法被响应,从而引起网络拥塞甚至系统瘫痪。
(2)Land攻击
向一个目标主机发送一个用于建立请求连接的TCPSYN报文而实现对目标主机的攻击。与正常的TCPSYN报文不同的是:LAND攻击报文的源IP地址和目的IP地址是相同的,都是目标主机的IP地址。由于目的IP地址和源IP地址是相同的,都是目标主机的IP地址,因此这个ACK报文就发给了目标主机本身。这样如果攻击者发送了足够多的SYN报文,则目标计算机的TCB可能会耗尽,最终不能正常服务。