|||
建立一个TCP连接时,进行三次握手,以确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。 客户端执行connect()时
刚开始客户端处于 Closed 的状态,服务端处于 Listen 状态。
第一次握手:客户端给服务端发一个SYN 报文,并指明客户端的初始化序列号seq。客户端处于SYN_SEND 状态, 报文段中同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。
第一次握手,客户端发送网络包,服务端收到了,就能得出结论:客户端的发送能力、服务端的接收能力是正常的。服务器此时处于SYN_RCVD 状态,但双方还没有完全建立其连接,服务器会把此种状态下请求连接放在一个队列里,这种队列我们称之为半连接队列。
第二次握手:服务器收到客户端的 SYN 报文之后,会以自己的SYN 报文作为应答,同时指定自己的初始化序列号 ISN(s),把客户端的 ISN(Initial Sequence Number) + 1 作为ACK 的值,表示自己已经收到了客户端的SYN,服务器此时处于SYN_REVD 的状态。服务端确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y。
第二次握手,服务端发包,客户端收到了,就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的,但此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端收到 SYN 报文之后,会发送一个 ACK 报文,把服务器的 ISN + 1 作为 ACK 的值,表示已经收到了服务端的 SYN 报文,此时客户端处于 ESTABLISHED 状态。服务器收到 ACK 报文之后,也处于 ESTABLISHED 状态,此时,双方已建立起了连接(第三次握手得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。)。报文段中ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段+1),ACK报文段可以携带数据,不携带数据则不消耗序号。发送第一个SYN的一端将执行主动打开(active open),接收这个SYN并发回下一个SYN的另一端执行被动打开(passive open)。
关于SYN-ACK 重传
服务器发送完SYN-ACK包,如果未收到客户确认包,服务器进行首次重传,等待一段时间仍未收到客户确认包,进行第二次重传。如果重传次数超过系统规定的最大重传次数,系统将该连接信息从半连接队列中删除。
服务器端资源分配是在二次握手时,而客户端的资源是在完成三次握手时,故服务器容易受到SYN洪泛攻击,客户端在短时间内伪造大量不存在的IP地址,并向服务端不断地发送SYN包,服务端回复确认包,等待客户端确认,由于源地址不存在,服务端需要不断重发直至超时,大量伪造的SYN包长时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络拥塞甚至系统瘫痪。为典型的 DoS/DDoS 攻击(linux下检测 netstat -n -p TCP | grep SYN_RECV)。
TCP的半关闭(half-close):TCP提供了连接的一端在结束它的发送后还能接收来自另一端数据的能力。
TCP 的连接的拆除需发送四个包,即四次挥手,客户端或服务器均可主动发起挥手动作。刚开始双方都处于 ESTABLISHED 状态,如客户端先发起关闭请求close():
第一次挥手:客户端发送 FIN 报文,报文中指定一个序列号,此时客户端处于 FIN_WAIT1(终止等待1) 状态,即发出连接释放报文段(FIN=1,序号seq=u),并停止再发送数据,主动关闭TCP连接,等待服务端的确认。
第二次挥手:服务端收到 FIN 之后,发送 ACK 报文,将客户端的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的报文了,此时服务端处于 CLOSE_WAIT (关闭等待)状态。即发出连接释放报文段确认报文段(ACK=1,确认号ack=u+1,序号seq=v),此时的TCP处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入FIN_WAIT2(终止等待2)状态,等待服务端发出的连接释放报文段。
第三次挥手:如服务端也想断开连接,则同客户端的第一次挥手一样,发送 FIN 报文,指定一个序列号。此时服务端处于 LAST_ACK (最后确认)的状态。即服务端再没有要向客户端发出的数据,服务端发出连接释放报文段(FIN=1,ACK=1,序号seq=w,确认号ack=u+1),等待客户端的确认。
第四次挥手:客户端收到 FIN 之后,发送一个 ACK 报文作为应答,把服务端的序列号值 +1 作为ACK 报文的序列号值,此时客户端处于 TIME_WAIT (时间等待)状态。需等待以确保服务端收到的 ACK 报文之后进入 CLOSED 状态,服务端收到 ACK 报文之后,处于关闭连接,CLOSED 状态。即客户端收到服务端的连接释放报文段后,对此发出确认报文段(ACK=1,seq=u+1,ack=w+1),此时TCP未释放掉,需要经过时间等待计时器设置的时间2MSL(Maximum Segment Lifetime)后,客户端才进入CLOSED状态。收到一个FIN只意味着在这一方向上没有数据流动。客户端执行主动关闭并进入TIME_WAIT是正常的,服务端通常执行被动关闭,不会进入TIME_WAIT状态。
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-23 19:12
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社