TCP 握手协定
在 TCP/IP 协定中,TCP 协定提供牢靠的连贯服务, 采纳三次握手建设一个连贯.
第一次握手:建设连贯时, 客户端发送 syn 包 (syn=j) 到服务器, 并进入 SYN_SEND 状态, 期待服务器确认;
SYN:同步序列编号 (Synchronize Sequence Numbers)
第二次握手:服务器收到 syn 包, 必须确认客户的 SYN(ack=j+1), 同时本人也发送一个 SYN 包(syn=k), 即 SYN+ACK 包, 此时服务器进入 SYN_RECV 状态;
第三次握手:客户端收到服务器的 SYN+ACK 包, 向服务器发送确认包 ACK(ack=k+1), 此包发送结束, 客户端和服务器进入 ESTABLISHED 状态, 实现三次握手.
实现三次握手, 客户端与服务器开始传送数据.
A 与 B 建设 TCP 连贯时:首先 A 向 B 发 SYN(同步申请),而后 B 回复 SYN+ACK(同步申请应答),最初 A 回复 ACK 确认,这样 TCP 的一次连贯(三次握手)的过程就建设了!
一、TCP 报文格式
TCP/IP 协定的详细信息参看《TCP/IP 协定详解》三卷本。上面是 TCP 报文格式图:
图 1 TCP 报文格式
上图中有几个字段须要重点介绍下:
(1)序号:Seq 序号,占 32 位,用来标识从 TCP 源端向目标端发送的字节流,发起方发送数据时对此进行标记。
(2)确认序号:Ack 序号,占 32 位,只有 ACK 标记位为 1 时,确认序号字段才无效,Ack=Seq+1。
(3)标记位:共 6 个,即 URG、ACK、PSH、RST、SYN、FIN 等,具体含意如下:
(A)URG:紧急指针(urgent pointer)无效。
(B)ACK:确认序号无效。
(C)PSH:接管方应该尽快将这个报文交给应用层。
(D)RST:重置连贯。
(E)SYN:发动一个新连贯。
(F)FIN:开释一个连贯。
须要留神的是:
(A)不要将确认序号 Ack 与标记位中的 ACK 搞混了。
(B)确认方 Ack= 发起方 Req+1,两端配对。
二、三次握手
所谓三次握手(Three-Way Handshake)即建设 TCP 连贯,就是指建设一个 TCP 连贯时,须要客户端和服务端总共发送 3 个包以确认连贯的建设。在 socket 编程中,这一过程由客户端执行 connect 来触发,整个流程如下图所示:
图 2 TCP 三次握手
(1)第一次握手:Client 将标记位 SYN 置为 1,随机产生一个值 seq=J,并将该数据包发送给 Server,Client 进入 SYN_SENT 状态,期待 Server 确认。
(2)第二次握手:Server 收到数据包后由标记位 SYN= 1 晓得 Client 申请建设连贯,Server 将标记位 SYN 和 ACK 都置为 1,ack=J+1,随机产生一个值 seq=K,并将该数据包发送给 Client 以确认连贯申请,Server 进入 SYN_RCVD 状态。
(3)第三次握手:Client 收到确认后,查看 ack 是否为 J +1,ACK 是否为 1,如果正确则将标记位 ACK 置为 1,ack=K+1,并将该数据包发送给 Server,Server 查看 ack 是否为 K +1,ACK 是否为 1,如果正确则连贯建设胜利,Client 和 Server 进入 ESTABLISHED 状态,实现三次握手,随后 Client 与 Server 之间能够开始传输数据了。
SYN 攻打:
在三次握手过程中,Server 发送 SYN-ACK 之后,收到 Client 的 ACK 之前的 TCP 连贯称为半连贯(half-open connect),此时 Server 处于 SYN_RCVD 状态,当收到 ACK 后,Server 转入 ESTABLISHED 状态。SYN 攻打就是 Client 在短时间内伪造大量不存在的 IP 地址,并向 Server 一直地发送 SYN 包,Server 回复确认包,并期待 Client 的确认,因为源地址是不存在的,因而,Server 须要一直重发直至超时,这些伪造的 SYN 包将产工夫占用未连贯队列,导致失常的 SYN 申请因为队列满而被抛弃,从而引起网络梗塞甚至零碎瘫痪。SYN 攻打时一种典型的 DDOS 攻打,检测 SYN 攻打的形式非常简单,即当 Server 上有大量半连贯状态且源 IP 地址是随机的,则能够判定受到 SYN 攻打了,应用如下命令能够让之现行:
#netstat -nap | grep SYN_RECV
三、四次挥手
三次握手耳熟能详,四次挥手预计就 ,所谓四次挥手(Four-Way Wavehand)即终止 TCP 连贯,就是指断开一个 TCP 连贯时,须要客户端和服务端总共发送 4 个包以确认连贯的断开。在 socket 编程中,这一过程 由客户端或服务端任一方执行 close 来触发,整个流程如下图所示:
图 3 TCP 四次挥手
因为 TCP 连贯时全双工的,因而,每个方向都必须要独自进行敞开,这一准则是当一方实现数据发送工作后,发送一个 FIN 来终止这一方向的连贯,收到一个 FIN 只是意味着这一方向上没有数据流动了,即不会再收到数据了,然而在这个 TCP 连贯上依然可能发送数据,直到这一方向也发送了 FIN。首先进行敞开的一方将执行被动敞开,而另一方则执行被动敞开,上图形容的即是如此。
(1)第一次挥手:Client 发送一个 FIN,用来敞开 Client 到 Server 的数据传送,Client 进入 FIN_WAIT_1 状态。
(2)第二次挥手:Server 收到 FIN 后,发送一个 ACK 给 Client,确认序号为收到序号 +1(与 SYN 雷同,一个 FIN 占用一个序号),Server 进入 CLOSE_WAIT 状态。
(3)第三次挥手:Server 发送一个 FIN,用来敞开 Server 到 Client 的数据传送,Server 进入 LAST_ACK 状态。
(4)第四次挥手:Client 收到 FIN 后,Client 进入 TIME_WAIT 状态,接着发送一个 ACK 给 Server,确认序号为收到序号 +1,Server 进入 CLOSED 状态,实现四次挥手。
下面是一方被动敞开,另一方被动敞开的状况,理论中还会呈现同时发动被动敞开的状况,具体流程如下图:
图 4 同时挥手
流程和状态在上图中曾经很明了了,在此不再赘述,能够参考后面的四次挥手解析步骤。
四、附注
对于三次握手与四次挥手通常都会有典型的面试题,在此提出供有需要的 XDJM 们参考:
(1)三次握手是什么或者流程?四次握手呢?答案后面剖析就是。
(2)为什么建设连贯是三次握手,而敞开连贯却是四次挥手呢?
这是因为服务端在 LISTEN 状态下,收到建设连贯申请的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。而敞开连贯时,当收到对方的 FIN 报文时,仅仅示意对方不再发送数据了然而还能接收数据,己方也未必全副数据都发送给对方了,所以己方能够立刻 close,也能够发送一些数据给对方后,再发送 FIN 报文给对方来表示同意当初敞开连贯,因而,己方 ACK 和 FIN 个别都会离开发送。
文章起源:https://blog.csdn.net/younglao/article/details/79453777