TCP、UDP、三次握手、四次挥手
# TCP、UDP
TCP是一个面向连接的、可靠的、基于字节流的传输层协议
UDP是一个面向无连接的传输层协议
面向连接。所谓的连接,指的是客户端和服务器的连接,在双方互相通信之前,TCP 需要三次握手建立连接,而 UDP 没有相应建立连接的过程
可靠性。TCP 花了非常多的功夫保证连接的可靠,这个可靠性体现在哪些方面呢?一个是有状态,另一个是可控制。 TCP 会精准记录哪些数据发送了,哪些数据被对方接收了,哪些没有被接收到,而且保证数据包按序到达,不允许半点差错。这是有状态
当意识到丢包了或者网络环境不佳,TCP 会根据具体情况调整自己的行为,控制自己的发送速度或者重发。这是可控制
面向字节流。UDP 的数据传输是基于数据报的,这是因为仅仅只是继承了 IP 层的特性,而 TCP 为了维护状态,将一个个 IP 包变成了字节流
# 说说 TCP 三次握手的过程?为什么是三次而不是两次、四次
主要证明双方的两种能力发送能力
和接受能力
从最开始双方都处于 CLOSED 状态。然后服务端开始监听某个端口,进入了 LISTEN 状态。
然后客户端主动发起连接,发送 SYN , 自己变成了 SYN-SENT 状态。
服务端接收到,返回 SYN 和 ACK(对应客户端发来的 SYN),自己变成了 SYN-REVD。
之后客户端再发送 ACK 给服务端,自己变成了 ESTABLISHED 状态;服务端收到 ACK 之后,也变成了 ESTABLISHED 状态
SYN 需要对端的确认, 而 ACK 并不需要,因此 SYN 消耗一个序列号而 ACK 不需要
# 为什么不是两次
根本原因: 无法确认客户端的接收能力。
分析如下: 如果是两次,你现在发了 SYN 报文想握手,但是这个包滞留在了当前的网络中迟迟没有到达,TCP 以为这是丢了包,于是重传,两次握手建立好了连接。 看似没有问题,但是连接关闭后,如果这个滞留在网路中的包到达了服务端呢?这时候由于是两次握手,服务端只要接收到然后发送相应的数据包,就默认建立连接,但是现在客户端已经断开了。 看到问题的吧,这就带来了连接资源的浪费。
# 为什么不是四次
三次握手的目的是确认双方发送和接收的能力,那四次握手可以嘛?
当然可以,100 次都可以。但为了解决问题,三次就足够了,再多用处就不大了。
# 三次握手过程中够可以携带数据么
第三次握手可以携带,前两次不能
如果前两次握手能够携带数据,那么一旦有人想攻击服务器,那么他只需要在第一次握手中的 SYN 报文中放大量数据,那么服务器势必会消耗更多的时间和内存空间去处理这些数据,增大了服务器被攻击的风险。 第三次握手的时候,客户端已经处于 ESTABLISHED 状态,并且已经能够确认服务器的接收、发送能力正常,这个时候相对安全了,可以携带数据。
# 四次挥手
刚开始双方处于 ESTABLISHED 状态。
客户端要断开了,向服务器发送 FIN 报文,在 TCP 报文中的位置如下图:
发送后客户端变成了 FIN-WAIT-1 状态。注意, 这时候客户端同时也变成了 half-close(半关闭)状态,即无法向服务端发送报文,只能接收。
服务端接收后向客户端确认,变成了 CLOSED-WAIT 状态。
客户端接收到了服务端的确认,变成了 FIN-WAIT2 状态。
随后,服务端向客户端发送 FIN,自己进入 LAST-ACK 状态,
客户端收到服务端发来的 FIN 后,自己变成了 TIME-WAIT 状态,然后发送 ACK 给服务端。
注意了,这个时候,客户端需要等待足够长的时间,具体来说,是 2 个 MSL(Maximum Segment Lifetime,报文最大生存时间), 在这段时间内如果客户端没有收到服务端的重发请求,那么表示 ACK 成功到达,挥手结束,否则客户端重发 ACK
# SYN Flood 攻击原理
SYN Flood 属于典型的 DoS/DDoS 攻击。其攻击的原理很简单,就是用客户端在短时间内伪造大量不存在的 IP 地址,并向服务端疯狂发送 SYN。对于服务端而言,会产生两个危险的后果:
处理大量的 SYN 包并返回对应 ACK, 势必有大量连接处于 SYN_RCVD 状态,从而占满整个半连接队列,无法处理正常的请求。
由于是不存在的 IP,服务端长时间收不到客户端的 ACK,会导致服务端不断重发数据,直到耗尽服务端的资源。
# 如何应对 SYN Flood 攻击?
- 增加 SYN 连接,也就是增加半连接队列的容量。
- 减少 SYN + ACK 重试次数,避免大量的超时重发。
- 利用 SYN Cookie 技术,在服务端接收到 SYN 后不立即分配连接资源,而是根据这个 SYN 计算出一个 Cookie,连同第二次握手回复给客户端,在客户端回复 ACK 的时候带上这个 Cookie 值,服务端验证 Cookie 合法之后才分配连接资源。
# 理解
一、三次握手讲解
客户端发送位码为 syn = 1,随机产生 seq number=1234567 的数据包到服务器,服务器由 SYN=1 知道客户端要求建立联机(客户端:我要连接你) 服务器收到请求后要确认联机信息,向 A 发送 ack number=(客户端的 seq+1),syn=1,ack=1,随机产生 seq=7654321 的包(服务器:好的,你来连吧) 客户端收到后检查 ack number 是否正确,即第一次发送的 seq number+1,以及位码 ack 是否为 1,若正确,客户端会再发送 ack number=(服务器的 seq+1),ack=1,服务器收到后确认 seq 值与 ack=1 则连接建立成功。(客户端:好的,我来了)
二、为什么 http 建立连接需要三次握手,不是两次或四次?
答:三次是最少的安全次数,两次不安全,四次浪费资源;
三、TCP 关闭连接过程
Client 向 Server 发送 FIN 包,表示 Client 主动要关闭连接,然后进入 FIN_WAIT_1 状态,等待 Server 返回 ACK 包。此后 Client 不能再向 Server 发送数据,但能读取数据。
Server 收到 FIN 包后向 Client 发送 ACK 包,然后进入 CLOSE_WAIT 状态,此后 Server 不能再读取数据,但可以继续向 Client 发送数据。
Client 收到 Server 返回的 ACK 包后进入 FIN_WAIT_2 状态,等待 Server 发送 FIN 包。
Server 完成数据的发送后,将 FIN 包发送给 Client,然后进入 LAST_ACK 状态,等待 Client 返回 ACK 包,此后 Server 既不能读取数据,也不能发送数据。
Client 收到 FIN 包后向 Server 发送 ACK 包,然后进入 TIME_WAIT 状态,接着等待足够长的时间(2MSL)以确保 Server 接收到 ACK 包,最后回到 CLOSED 状态,释放网络资源。
Server 收到 Client 返回的 ACK 包后便回到 CLOSED 状态,释放网络资源。
四、为什么要四次挥手?
TCP 是全双工信道,何为全双工就是客户端与服务端建立两条通道,通道 1:客户端的输出连接服务端的输入;通道 2:客户端的输入连接服务端的输出。两个通道可以同时工作:客户端向服务端发送信号的同时服务端也可以向客户端发送信号。所以关闭双通道的时候就是这样:
客户端:我要关闭输入通道了。 服务端:好的,你关闭吧,我这边也关闭这个通道。
服务端:我也要关闭输入通道了。 客户端:好的你关闭吧,我也把这个通道关闭。