一图学完!计算机网络(TCP三次握手四次挥手)含面试题(下篇)


一图学完!计算机网络(TCP等)含面试题(上篇)

1.TCP三次握手

标志位: ACK:确认序号标志,为1时有效,为0则忽略。SYN:同步序号,用于建立连接

1. 客户端发送确认序号SYN=1,初始序号seq=x的包,连接服务器的端口。此时客户端进入SYN-SENT状态。

2. 服务器返回确认包ack=x+1,并发送一个自己的序号seq=y。此时服务器由LISTEN变为SYN-RCVD状态。

3. 客户端收到确认包后进入ESTABLISHED(连接成功)状态,客户端发送ACK=1,ack=y+1,序列号设置为第二次的确认号x+1。服务器收到后也进入连接成功状态。
在这里插入图片描述

建立连接三次握手解释:
1.客户端: 让我们建立连接吧,我发送的信息序号会从x(seq)开始。
2.服务器: 收到,我已经准备好接受序号为x+1(ack)的信息了,我发送的信息序号会从y(seq)开始。
3.客户端: 很好,我也收到了你的序号,可以向我发送编号y+1(ack)的信息了。

2.TCP四次挥手

标志位: FIN:finish标志,用于释放连接。(TCP连接是全双工的,因此每个方向都必须单独进行关闭)

1. 首先客户端与服务器端处于连接状态,客户端发送FIN=1,ACK=1, seq = u,的断开连接请求报文,客户端进入到FIN-WAIT1状态。

2. 服务器接收后,立即发送ACK=1,seq=v,ack=u+1 的确认收到的报文,并断开客户端发送信息,服务器接收信息的那一条连接,但保留服务器发送信息,进入到CLOSE-WAIT状态。

3. 客户端接收到第二次挥手信息进入FIN-WAIT2状态,tcp连接进入半关闭状态,此时只能由服务器发送数据,客户端接收数据。

4. 之后第三次挥手是服务器端发送完毕,向客户端发送FIN=1,ACK=1,seq=w,ack=u+1的断开连接报文,服务器进入到LAST-ACK状态,客户端接收到第三次挥手信息后,发送ACK=1,seq=u+1,ack=w+1,的确认报文,进入TIME-WAIT状态,时长2MSL,服务器接收到后,进入CLOSE状态。
在这里插入图片描述
TIME-WAIT状态: 目的是为了防止服务器端没有收到第四次握手的确认报文,假如没有收到确认报文,那么服务器的第三次挥手会超时重传,处于TIME-WAIT的客户端这时候可以发送确认报文,以关闭服务器,避免浪费资源。

Ex: 一个正常的TCP连接需要三次握手,首先客户端发送一个包含SYN标志的数据包,其后服务器返回一个SYN/ACK的应答包,表示客户端的请求被接受,最后客户端再返回一个确认包ACK,这样才完成TCP连接。在服务器端发送应答包后,如果客户端不发出确认,服务器会等待到超时,期间这些半连接状态都保存在一个空间有限的缓存队列中;如果大量的SYN包发到服务器端后没有应答,就会使服务器端的TCP资源迅速耗尽,导致正常的连接不能进入,甚至会导致服务器的系统崩溃。

3.问题分析

3.1.为什么不能用两次握手进行连接?

参考:
为了实现可靠数据传输, TCP 协议的通信双方, 都必须维护一个序列号, 以标识发送出去的数据包中, 哪些是已经被对方收到的。 三次握手的过程即是通信双方相互告知序列号起始值, 并确认对方已经收到了序列号起始值的必经步骤。
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认。
三次握手完成了两个重要功能。令双方都知道彼此已准备好,同时也确认了双方发送的序列号。另一个原因是可能发生死锁(防止已失效的请求连接报文忽然又传送到了,从而产生错误)。
参考连接

3.2.如果已经建立了连接,但是客户端突然出现故障怎么办?

参考: Keepalive(保活定时器)
Keepalive的使用: 检测tcp socket并检测连接是否在运行或者是否被破坏
TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒钟发送一次。若一连发送9个探测报文仍然没反应(总共7200+75*9的时间),服务器就认为客户端出了故障,接着就关闭连接。
相关参数:

tcp_keepalive_time 7200// 距离上次传送数据多少时间未收到新报文判断为开始检测,单位秒,默认7200s
tcp_keepalive_intvl 75// 检测开始每多少时间发送心跳包,单位秒,默认75s
tcp_keepalive_probes 9// 发送几次心跳包对方未响应则close连接,默认9次

3.3.SYN Flood攻击

说明: 三次握手是有缺陷的,在第二次握手中,当服务器发送了SYN+ACK报文后,若该连接的定时器超过超时重传时间服务器会对报文进行重传,当重传次数超过一定次数后,服务器认为TCP连接超时,而后才销毁套接字,释放TCP,如果攻击者用很快的速度,连续对目标服务器开放的端口发送SYN报文,服务器的所有资源将被消耗,以至于不能接收其他客户的正常连接请求。

攻击检测以及防御手段:
目前对于SYN Flood攻击一般通过实时检测tcp的新建连接速率来判断。防御的前提是区分出哪些请求是合法的,哪些是SYN泛洪,下面是实现SYN cookies的三种不同方式。

方法一:(reset认证)
1、当安全设备获取到发往服务器的SYN报文后,设备模拟服务器端会给此源IP回复ACK=Cookie的SYN/ACK报文
2、正常客户端会回复RST报文,攻击流不会回复
3、安全设备收到RST报文并校验后可把正确报文的客户端IP加入到白名单
4、后续安全设备放行属于该IP的正常流量

方法二:(cookie源认证)
1、当安全设备获取到发往服务器的SYN报文后,设备模拟服务器端会给此源IP回复ACK=Cookie的SYN/ACK报文
2、正常客户端回复ACK报文,确认序号为Cookie+1
3、安全设备收到ACK报文,并校验无误后,将该客户端的IP加入到白名单,并向客户端发送RST报文断开连接
4、后续安全设备放行属于该IP的正常流量

方法三:
1、当安全设备获取到发往服务器的SYN报文后,设备模拟服务器给源IP回复seq=Cookie的SYN/ACK报文
2、正常客户端回复ACK报文,确认序号为Cookie+1
3、安全设备收到ACK报文并校验无误后,设备与服务发送连接请求,通过三次握手后与服务器建立起连接
4、客户端与防火墙之间建立了连接,防火墙与服务器之间也建立了连接,客户端与服务器间关于此次连接的后续数据报文都通过安全设备代理转发

3.4.TCP粘包半粘包和拆包问题

在这里插入图片描述

如图: 假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的
故可能存在以下四种情况:
1.服务端分两次读取到了两个独立的数据包,分别是D1和D2,没有粘包和拆包

2.服务端一次接受到了两个数据包,D1和D2粘合在一起,称之为TCP粘包

3.服务端分两次读取到了数据包,第一次读取到了完整的D1包和D2包的部分内容,第二次读取到了D2包的剩余内容,这称之为TCP拆包

4.服务端分两次读取到了数据包,第一次读取到了D1包的部分内容D1_1,第二次读取到了D1包的剩余部分内容D1_2和完整的D2包。

PS: 特别要注意的是,如果TCP的接受滑窗非常小,而数据包D1和D2比较大,很有可能会发生第五种情况,即服务端分多次才能将D1和D2包完全接受,期间发生多次拆包。

粘包问题:
如果TCP数据报很短,远小于套接字缓冲区的大小,TCP将多次写入缓冲区的数据一次发送出去。将会发生粘包现象。
接收数据端的应用层没有及时的读取缓冲区中的数据,也会发生粘包。

拆包问题:
要发送的数据大于TCP发送缓冲区剩余空间的大小,将会发生拆包。
要发送的数据大于MSS(最大报文长度),TCP在传输前将进行拆包。

解决方法:
在报头首部添加数据包的长度。
发送端将每个数据包封装为固定长度(不够的的可以用0来补充)
特殊字符来设置边界进行控制。

在这里插入图片描述
有什么错误或者补充请留言。

猜你喜欢

转载自blog.csdn.net/qq374461948/article/details/105864140