前言
UDP(User Data Protocol)用户数据协议和TCP (Transition control Protocol)传输控制协议,是传输层的两种协议,TCP面向连接,UDP面向无连接。
1. UDP和TCP的区别
- TCP是面向连接的,连接需要一定的时间,但保证了传输的稳定性,UDP面向无连接即时性高,但不稳定,容易丢包。
- TCP的报文要包含SYN和ACK,首部占用比较多的字节,最少需要20个,UDP的首部只需要8个字节
- TCP的传输方式是字节流,UDP的传输方式是数据包
- TCP只能对多连接,UDP比较随意,可以一对多,多对一或者多对多
UDP | TCP | |
---|---|---|
是否面向连接 | 否 | 是 |
是否可靠 | 否 | 是 |
即时性 | 高 | 低 |
首部开销 | 8个字节 | 20~60个字节 |
层传输方式 | 数据包 | 字节 |
连接方式 | 一对多、多对一、多对多 | 只能一对一 |
适用场景 | 适用于实时应用如视频会议、直播、IP电话等 | 适用于要求可靠传输的应用如文件传输 |
需要注意的是不是所有的流媒体都基于UDP,如直播常用的传输协议RTMP和HLS都是基于TCP的
2.三次握手
2.1 三次握手的过程
- 第一次客户端向服务发送建立连接的请求,报文首部同部位SYN=1,初始序号seq = x,发送成功后客户端状态由closed变为syn_send。
- 第二次握手服务端收到客户端建立连接的请求,确认后向客户端发送建立连接的请求,确认位ACK=1,确认序列号ack = x+1,同步位SYN = 1,同步序列号seq = y,发送成功后服务端的状态由listen变为syn_received。
- 第三次握手,客户端确认后向服务端发送确认报文ACK= 1,确认序列号ack = y+1,序号seq = x+1(因为初始值是x),此时客户端的状态变为established,服务端收到ACK报文后转态也变成established,此时双发已经建立连接。
如果将发送建立连接请求和确认收到请求作为一次连接的话,三次握手可以看做两次连接确认和一次syn的确认:
- 客户端向服务端建立连接服务端同意
- 服务端向客户端建立连接客户端同意
- 客户端确认是最新的syn后同意建立连接
2.2 为什么是三次握手?
第一次握手确认了客户端的发送能力和服务端的接收能力,第二此握手确认了客户端和服务端的发送和接收能力。第三握手确认syn是最新的,是为了防止网络延迟,导致服务端一直处于等待状态,造成资源的浪费。具体过程是这样的:
假如客户端发送SYN的时候网络节点中出现延迟,客户端等不到服务端的ACK,会再次发送SYN,服务端收到SYN并且成功跟客户端建立连接,之后服务端接收到了被延迟的SYN,向客户端发送ACK确认进行第二次握手,客户端经过判断发现这个SYN是重新上传过的并且已经成功建立连接了,就不会再向服务端发送ACK,服务端收不到客户端的确认ACK就一直处于等待状态。
3. 四次挥手
- 第一次挥手:客户端向服务端发送FIN
- 服务端向客户端发送确认的ACK
- 服务端向客户端发送FIN申请关闭连接
- 客户端向服务端发送ACK,服务端收到ACK变为closed状态,客户端等待2MSL后变为closed状态,此时挥手完成
四次挥手整体可以看做是两关闭连接(FIN)请求和请求确认(ACK)的过程。
3.2 为什么是四次挥手?不能是三次握手吗?服务端的FIN不能跟ACK一起发送吗?
四次挥手是因为每次FIN都都要经过ACK的确认,服务端在收到FIN不能立即关闭是因为服务端可能还有没发送完的数据,服务器在等数据发送完成后才会主动发送FIN申请关闭连接。
3.3 为什么客户端要等待2MSL后才关闭?
- 确保服务端收到ACK
- 确保2MSL内没有新的报文到客户端
确保服务端成功收到ACK后变成关闭状态。2MSL是两个报文的最大生存时间,够数据传输的一个来回。在2MSL时间内如果客户端没有再接收到服务端的数据,说明服务端已经成功关,这时客户端才变为关闭状态,四次挥手完成。
3.4 TCP是否每次都需要三次握手?
使用fast-open只需要两次握手
- 客户端发送syn的时候在fast-open上携带上cookie
- 服务端产生cookie在ACK中返回给客户端
- 客户端存储cookie
之后客户端发送syn都会携带式cookie,服务端验证cookie有效后会在ACK中直接将数据返回,只需要两次握手,如果验证cookie无效再进行三次握手。
3.5 常见的TCP攻击方式
- 半连接和全连接
- 客户端发送SYN请求,服务端收到后向客户端发送ACK和SYN,状态从LISTEN变为SYN_RCVD,此时这个连接就被推入了SYN队列也就是半连接队列,当客户端收到SYN返回ACK后三次握手完成,这个连接会被推入TCP队列,也就是全连接。
SYN flood攻击
当客户端短时间内发送大量的SYN的时候,服务端返回大量的ACK,半连接池吃紧,服务端收不到客户端的ACK,超时重发
如何解决?
- 加大半连接池
- SYN cookie: 服务端在接收到SYN后不立即分配资源,根据SYN计算出cookie携带在在返回的ACK上,客户端客户端在ACK里面加上cookie,服务端校验cooike正确分配资源。
传送门:OSI七层模型和TCP/IP协议