扩展-链接:表白小游戏教程(零基础也能学会)
1. 请详细介绍一下 TCP 的三次握手机制,为什么要三次握手?
在讲三次握手之前首先要介绍 TCP 报文中两个重要的字段:一个是序号字段,另一个是确认号字段,这两个字段将在握手阶段以及整个信息传输过程起到重要作用。
- 第一步:客户端 TCP 向服务端的TCP发送一个不带额外数据的特殊 TCP 报文段,该报文段的 SYN 标志位会被置1,所以把它称为 SYN 报文段。这时客户端会选取一个初始序列号(假设为 client_num),并将此编号放置在序号字段中。该报文段会被封装在一个IP数据报中发送给服务器。
- 第二步:服务器接收到 SYN 报文段后,会为该 TCP 分配缓存和变量,并发送允许连接的确认报文。在允许连接的报文中,SYN 标志位仍被置为1,确认号字段填的是 client_num + 1的值。最后服务端也会选取一个 server_num 存放到序号字段中,这个报文段称为 SYNACK 报文段。
- 第三步:在接收到 SYNACK 报文段后,客户端最后也要向服务端发送一个确认报文,这个报文和前两个不一样,SYN 标志位置0,在确认号字段中填上 server_num + 1的值,并且这个报文段可以携带数据。一旦完成这3个步骤,客户端和服务器之间就可以相互发送包含数据的报文了。
如果不是三次握手,二次两次的话,服务器就不知道客户端是否接收到了自己的 SYNACK 报文段,从而无法建立连接;四次握手就显得多余了。
2. 讲一讲SYN超时,洪泛攻击,以及解决策略
什么 SYN 是洪泛攻击? 在 TCP 的三次握手机制的第一步中,客户端会向服务器发送 SYN 报文段。服务器接收到 SYN 报文段后会为该TCP分配缓存和变量,如果攻击分子大量地往服务器发送 SYN 报文段,服务器的连接资源终将被耗尽,导致内存溢出无法继续服务。
解决策略:
当服务器接受到 SYN 报文段时,不直接为该 TCP 分配资源,而只是打开一个半开的套接字。接着会使用 SYN 报文段的源Id,目的Id,端口号以及只有服务器自己知道的一个秘密函数生成一个 cookie,并把 cookie 作为序列号响应给客户端。
如果客户端是正常建立连接,将会返回一个确认字段为 cookie + 1 的报文段。接下来服务器会根据确认报文的源Id,目的Id,端口号以及秘密函数计算出一个结果,如果结果的值 + 1等于确认字段的值,则证明是刚刚请求连接的客户端,这时候才为该 TCP 分配资源
这样一来就不会为恶意攻击的 SYN 报文段分配资源空间,避免了攻击。
3. 详细介绍一下TCP的四次挥手机制,为什么要有TIME_WAIT状态,为什么需要四次握手?服务器出现了大量CLOSE_WAIT状态如何解决
当客户端要服务器断开连接时,客户端 TCP 会向服务器发送一个特殊的报文段,该报文段的 FIN 标志位会被置1,接着服务器会向客户端发送一个确认报文段。然后服务器也会客户端发送一个 FIN 标志位为1的终止报文段,随后客户端回送一个确认报文段,服务器立即断开连接。客户端等待一段时间后也断开连接。
其实四次挥手的过程是很容易理解的,由于 TCP 协议是全双工的,也就是说客户端和服务端都可以发起断开连接。两边各发起一次断开连接的申请,加上各自的两次确认,看起来就像执行了四次挥手。
为什么要有 TIME_WAIT 状态?因为客户端最后向服务器发送的确认 ACK 是有可能丢失的,当出现超时,服务端会再次发送 FIN 报文段,如果客户端已经关闭了就收不到了。还有一点是避免新旧连接混杂。
大量 CLOSE_WAIT 表示程序出现了问题,对方的 socket 已经关闭连接,而我方忙于读或写没有及时关闭连接,需要检查代码,特别是释放资源的代码,或者是处理请求的线程配置。
详情可参考以下博客:
https://www.cnblogs.com/sunxucool/p/3449068.html
4. 详细讲一下TCP的滑动窗口
从上面的图可以看到滑动窗口左边的是已发送并且被确认的分组,滑动窗口右边是还没有轮到的分组。滑动窗口