tcp握手过程

TCP结构:

1

SYN是同步的缩写,SYN 段是发送到另一台计算机的 TCP 数据包,请求在它们之间建立连接

ACK 是“确认”的缩写。 ACK 数据包是任何确认收到一条消息或一系列数据包的 TCP 数据包

TCP三次握手如图:

tcp三次握手

1.1第一次握手

客户端给服务器发送一个SYN标志位为1的 TCP/IP 数据包, 该包中客户端的初始序列号(Sequence number = J)。

1.2第二次握手

服务器返回客户端 SYN +ACK两个标志位都为为1的 TCP/IP 数据包,该包中服务器的初始序列号(Sequence number = K);同时使 Acknowledgment number = J + 1来表示确认已收到客户端的 SYN段。

1.3第三次握手

客户端给服务器响应一个ACK标志位为1的 TCP/IP 数据包, 该包中使 Acknowledgment number = K + 1来表示确认已收到服务器的 SYN段。

解释一下 三次握手 和 四次挥手?

三次握手:

第一次:客户端向服务器发送syn包,此时进入[SYN_SENT]状态,等待服务器返回信息;此时服务端确认了客户端发送是正常的

第二次:服务器收到syn包,需要确认客户端的syn包,同时自己发出一个syn+ask包给客户端;此时客户端知道了自己发送、接收正常,客户端也知道服务器发送接收也正常;但是服务器不知道客户端接收是否正常,也不知道自己发送是否正常。

第三次:[客户端]收到服务器的syn+ask包后,向服务器发送确认包ask,此包发送完毕,客户端和服务器进入[ESTABLISHED](TCP连接成功)状态;双方都知道对方发送和接收都正常。

为什么不能两次握手:

假如A发出了一个由于网络异常变成了失效的连接a;当a到达B,那么只要B确认,新的连接就建立了。B会一直等待A发送数据,这样就造成了资源浪费。

为什么不能四次握手:

3次就可以解决问题了,为什么要四次


TCP三次握手详细解析过程:

2

1.1 第一次握手

客户在socket() connect()后主动(active open)连接上服务器, 发送SYN ,这时客户端的状态是SYN_SENT

服务器在进行socket(),bind(),listen()后等待客户的连接,收到客户端的 SYN 后,

1.1.1 半连接队列(syn queue)未满

服务器将该连接的状态变为SYN_RCVD, 服务器把连接信息放到半连接队列(syn queue)里面。

1.1.2 半连接队列(syn queue)已满

服务器不会将该连接的状态变为SYN_RCVD,且将该连接丢弃(SYN flood攻击就是利用这个原理,

对于SYN foold攻击,应对方法之一是使syncookies生效,将其值置1即可,路径/proc/sys/net/ipv4/tcp_syncookies,

即使是半连接队列syn queue已经满了,也可以接收正常的非恶意攻击的客户端的请求,

1.2 第二次握手

服务器返回SYN+ACK段给到客户端,客户端收到SYN+ACK段后,客户端的状态从SYN_SENT变为ESTABLISHED,

也即是connect()函数的返回。

1.3 第三次握手

全连接队列(accept queue)的最大值 /proc/sys/net/core/somaxconn (默认128)

1.3.1 全连接队列(accept queue)未满

服务器收到客户端发来的ACK, 服务端该连接的状态从SYN_RCVD变为ESTABLISHED,

然后服务器将该连接从半连接队列(syn queue)里面移除,且将该连接的信息放到全连接队列(accept queue)里面。

1.3.2 全连接队列(accept queue)已满

服务器收到客户端发来的ACK, 不会将该连接的状态从SYN_RCVD变为ESTABLISHED。

当然全连接队列(accept queue)已满时,则根据 tcp_abort_on_overflow 的值来执行相应动作


SYN flood攻击

攻击方的客户端只发送SYN分节给服务器,然后对服务器发回来的SYN+ACK什么也不做,直接忽略掉,

不发送ACK给服务器;这样就可以占据着服务器的半连接队列的资源,导致正常的客户端连接无法连接上服务器。

(SYN flood攻击的方式其实也分两种,第一种,攻击方的客户端一直发送SYN,对于服务器回应的SYN+ACK什么也不做,不回应ACK, 第二种,攻击方的客户端发送SYN时,将源IP改为一个虚假的IP, 然后服务器将SYN+ACK发送到虚假的IP, 这样当然永远也得不到ACK的回应。)

https://blog.csdn.net/jun2016425/article/details/81506353

四次挥手:

假设Client端发起中断连接请求,也就是发送FIN报文。

Server端接到FIN报文后,意思是说”我Client端没有数据要发给你了”,但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以 Server 端会先发送ACK,”告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候Client端就进入 FIN_WAIT 状态,继续等待Server端的FIN报文。

当Server端确定数据已发送完成,则向Client端发送FIN报文,”告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。

Client端收到FIN报文后,”就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送 ACK 后进入 TIME_WAIT 状态,如果 Server 端没有收到 ACK 则可以重传“,Server端收到ACK后,”就知道可以断开连接了”。

Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

整个过程:

A向B发起请求,表示A没有数据要发送了:A——>B;

B向A发送信号,确认A的断开请求请求:B——>A;

B向A发送信号,请求断开连接,表示B没有数据要发送了:B——>A;

A向B发送确认信号,同意断开:A——>B。

为什么2、3次挥手不能合在一次挥手中?那是因为此时A虽然不再发送数据了,但是还可以接收数据,B可能还有数据要发送给A,所以两次挥手不能合并为一次。

为什么挥手次数比握手多一次? 是因为握手过程,通信只需要处理连接。而挥手过程,通信需要处理数据+连接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容