TCP和UDP的区别
- UDP是无连接的,即发送数据之前不需要建立连接;TCP面向连接的,即在发送数据之前需要建立连接,发送数据完毕需要释放
- UDP尽最大努力交付,即不保证可靠交付,因此
主机不需要维护复杂的连接状态表
;TCP提供可靠交付,通过TCP传送的数据,无差错
、不丢失
、不重复
,并且按序到达
。 - UDP是面向报文的,对于应用程序传下来的报文不合并也不拆分,只是添加 UDP 首部;TCP是面向字节流的,把应用层交下来的数据仅看做是
无结构的字节流
,把字节流组织成大小不等的数据块。 - UDP没有拥塞控制,网络出现拥塞不会使源主机的发送速率降低。这
对某些实时应用很重要
,比如IP电话
、实时视频会议
等。TCP提供流量控制、拥塞控制。 - UDP支持一对一、一对多、多对一和多对多的交互通信,TCP提供全双工通信,每一条 TCP 连接只能是点对点的(一对一)。
1. UDP(User Datagram Protocol)
① UDP是面向报文的
- 应用层交下来的数据,UDP不拆分也不合并,只是添加UDP首部。
- UDP协议的数据单元叫用户数据报,它只有首部字段和数据字段。首部字段只有
8个字节
,4个字段组成
,每个字段的长度都是2个字节
。
- 源端口: 源端口号,
在需要对方回信时选用
,不需要时可用全0
。 - 目的端口: 目的端口号,
在终点交付报文时必须要使用
。 - 长度: 用户数据报的长度,
最小值为8(仅有首部)
。 - 检验和: 检测用户数据报在传输过程中是否有错,
有错就丢弃
。
- 用户数据报中检验和的计算方法有些特殊:
- 在计算检验和时,要在用户数据报之前添加
12个字节
的伪首部。 - 伪首部只是为了计算检验和,既不向下传送也不向上递交。
- IP数据报的检验只检验IP数据报的首部,而用户数据报的检验是把首部和数据部分一起都检验。
- 检验时把伪首部和用户数据报看成16 bit的字串接起来,如果
用户数据报的数据字段不是偶数个字节
,需要在末尾填入一个全零字节(但该字节不发送)。
- 伪首部的内容包括:
- 源IP地址:4个字节
- 目的IP地址:4 个字节
- 0:1个字节
- 17:2个字节,IP数据报首部中的协议字段的值,对UDP此协议字段的值是17
- UDP长度:2个字节,记录用户数据报的长度
2. TCP(Transmission Control Protocol)
① TCP报文段结构
- TCP的数据单元叫报文段,包括首部和数据两部分。其中首部前20个字节是固定的,后面的
4
n
4n
4n个字节是可变的。因此,
TCP首部的最小长度为20字节
。
- 首部前20个字节的固定部分:
-
源端口和目的端口: 各占2个字节,与UDP的分用相似。
-
序号(seq): 4个字节,范围 [ 0 , 2 32 − 1 ] [0,2^{32}-1] [0,232−1],使用mod 2 32 2^{32} 232运算。TCP中传送的数据按字节进行编号,序号的值表示当前报文段数据的第一个字节序号。例如当前报文的
seq=301
,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的seq=401
。 -
确认号(ack) : 4 字节,期望收到对方下一个报文段数据的第一个字节序号。例如 B 正确收到 A 发送来的一个报文段,
seq=501
,携带的数据长度为 200 字节,因此 B 期望下一个报文段的seq = 701
,B 发送给 A 的确认报文段中ack=701
。
若ack=N
,表示之前的N个字节(序号从0开始, 0 ~ N − 1 0~N-1 0~N−1)的数据已经全部收到。 -
数据偏移 : 4 bit,表示数据部分距离报文段起始处的偏移量,实际上指的是
报文段首部长度
。数据偏移的单位是4字节,首部的最大长度
为 15 ∗ 4 = 60 15*4=60 15∗4=60字节,对应的数据偏移为15
;最小长度为固定部分的 20 20 20字节,对应的数据偏移为5
。 -
保留: 6 bit,保留为今后使用,
目前置为0
。 -
以下6个控制位都只占1 bit:
紧急URG:必须与紧急指针字段配合使用
,URG=1表明紧急指针有效,告诉系统此报文段中有紧急数据,应该尽快传送,而不是按原来的排队顺序传送。
确认ACK: 即acknowledge
,当ACK=1
时确认序号字段有效
,否则无效。TCP 规定,在连接建立后所有传送的报文段都必须把 ACK 置 1。
推送PSH(push): 接收方TCP 收到PSH=1
的报文段,就尽快地交付给接收应用进程,而不再等到整个缓存都填满了后再向上交付。
复位RST(reset) 当RST= 1
时,表明 TCP 连接中出现严重差错(如由于主机崩溃或其他原因)
,必须释放连接,然后再重新建立传输连接。
同步SYN: 即sychronization
,在连接建立时用来同步序号。当SYN=1,ACK=0
时表示这是一个连接请求报文段。若对方同意建立连接,则响应报文中SYN=1,ACK=1
。
终止 FIN : 用来释放一个连接,当FIN=1
时,表示此报文段的发送方的数据已发送完毕
,并要求释放连接
。 -
窗口: 2个字节,范围 [ 0 , 2 16 − 1 ] [0,2^{16}-1] [0,216−1],该字段的值明确指出了接收方允许发送方发送的数据量,
该值经常在动态变化
。 -
检验和: 2个字节,检验范围包括首部和数据这两部分。进行检验时与UDP一样,也
需要加上12字节的伪首部
。内容只是将17改为了6,UDP长度改为了TCP长度。 -
紧急指针: 2个字节,要
URG=1
此字段才有效,指明报文段中紧急数据的字节数(紧急数据之后就是普通数据)。 -
选项: 长度可变,
最大长度为40字节
。长度必须为4字节的整数倍
,如果不够在尾部进行填充。
- 接收数据后,ack发生变化;发送数据后,seq发生变化。
- 例如,服务器最初ack为 x x x,收到客户端的 y y y字节数据后,ack变为 x + y x+y x+y;服务器最初seq为 m m m,向客户端 n n n字节的数据后,seq变为 m + n m+n m+n。
② TCP的三次握手
- 初始时: 服务器B 处于
LISTEN(监听)状态
,等待客户的连接请求。如有,立即做出响应。 - 第一次握手: 客户A向服务器B
发送连接请求报文段
,SYN=1
,同时选择一个初始序号seq=x
。这时客户A进入SYN-SENT(同步已发送)状态
。注意: TCP规定,SYN=1的报文段不能携带数据
,但要消耗掉一个序号。 - 第二次握手:
服务器B收到连接请求报文段
,如果同意建立连接
,则向客户A发送确认
。在确认报文段中,SYN=1
,ACK=1
,确认序号ack=x+1
。同时也为自己选择一个初始序号seq=y
,这时服务器B进入SYN-RCVD(同步收到)状态
。注意: 这个报文段也不能携带数据,但要消耗掉一个序号
。 - 第三次握手: 客户A收到服务器B的确认后,还要向B发出确认。确认报文段中,
ACK=1
,确认序号ack=y+1
,自己的序号seq=x+1
。这时,客户A进入ESTABLISHED(已建立连接)状态
。而服务器B在收到客户A的确认后,也进入ESTABLISHED(已建立连接)状态
。注意: TCP规定,ACK报文段中可以携带数据,如果不携带则不消耗序号。在这种情况下,下一个报文段的序号仍为seq=x+1
。
为什么是三次握手?而不是两次握手或者四次?
- 第三次握手是为了防止失效的连接请求到达服务器,让服务器错误打开连接。
- 客户端发送的
连接请求如果在网络中滞留
,那么就会隔很长一段时间才能收到服务器端发回的连接确认。 - 客户端等待一个超时重传时间之后,就会
重新请求连接
。但是这个滞留的连接请求最后还是会到达服务器
,如果不进行三次握手
,服务器就会为客户端打开第二个连接。 - 而
客户端以为这个连接请求已经失效
,不会通过该连接进行数据传输,这样就白白浪费了服务器的资源
。 - 如果有第三次握手,
客户端会忽略服务器之后发送的对滞留连接请求的连接确认
,不进行第三次握手
,因此服务器就不会再次打开连接
。 - 三次握手后,客户端和服务器已经建立了可靠的连接。四次握手,甚至更多次握手都是徒劳的,只会
影响建立连接的速度
。
参考链接:【漫画】TCP连接为什么是三次握手,而不是两次握手,也不是四次握手?
③ TCP的四次挥手
- 初始时: 客户和服务器都是
ESTABLISHED(已建立连接)状态
。 - 第一次挥手:
客户向服务器发送连接释放报文段
,FIN=1
,序号seq=u
,该序号是客户已经发送的报文段数据最后一个字节序号+1
。这时,客户进入FIN-WAIT-1(终止等待1)状态
,等待服务器的确认。注意: TCP规定,FIN报文即使不携带数据
,但是也消耗掉一个序号
。 - 第二次挥手: 服务器收到客户的连接释报文段后立即发出确认,
ACK=1
,确认序号ack=u+1
,序号seq=v
。该序号是服务器已经发送的报文段数据的最后一个字节序号+1
。这时,服务器进入CLOSE-WAIT(关闭等待)状态
。客户收到服务器的确认后,进入FIN-WAIT-2(终止等待2) 状态
,等待服务器发出的连接释放报文段 。注意: 服务器的CLOSE-WAIT(关闭等待)状态
是一种半关闭状态,即客户不能向服务器发送数据了,而服务器能向客户发送数据。 - 第三次挥手: 服务器将未发送完的数据传送完毕了,向客户发送连接释放报文段,
FIN=1
,ACK=1
,确认序号ack=u+1
,seq=w
(服务器处于半关闭状态时,又向客户发送了一些数据)。这时,服务器进入LAST-ACK(最后确认)状态
。 - 第四次挥手: 客户收到服务器的连接释放报文段后立即做出确认,
ACK=1
,确认序号ack=w+1
,seq=u+1
。此时,客户进入TIME-WAIT(时间等待)状态
,需要等待2MSL(max segment lifetime,最大报文段寿命)
后,才能进入CLOSED状态
。服务器收到客户的确认后,立即进入CLOSED状态
。
什么时候由谁进入TIME-WAIT 状态?为什么要进入此状态?
- 客户在收到服务器的连接释放请求,并做出确认后进入
TIME-WAIT状态
。客户需要等待2MSL
后,才能进入CLOSED状态
。 - 这么做的理由有两个:
- 保证客户端发送的最后一个确认报文段能到达服务器。 如果这个确认报文段丢失,处于
LAST-ACK状态
的服务器会超时重传
连接释放报文段。这时,处于TIME-WAIT状态的客户可以再次进行确认
,并重启2MSL计时器
。最终,客户和服务器都能进入CLOSED状态
。如果不进行TIME-WAIT
,则服务器无法按正常步骤进入CLOSED状态
。 - 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接中不会出现旧的连接请求报文段。
为什么是四次挥手?
- TCP是一个全双工协议,必须单独拆除每一条信道。4次挥手能分别在一个方向上终止该方向的数据传输,达到终止数据传输的目的。
- 客户向服务器发送连接释放报文段,只是表明客户不需要再向服务器发送数据了。
- 而
服务器可能还需要向客户发送数据
,因此服务器收到这个报文并进行确认后只是进入了CLOSE-WAIT 状态
。 - 只有当服务器将还未发送的数据传送完毕后,才会发送连接释放报文段,使得客户和服务器都进入
CLOSED状态
。
WireShark抓包,只有“三次”挥手
-
最近进行数据抓包,发现竟然只有“三次”挥手
-
看了好多wireshark的抓包数据分析,人家都是四次挥手
① wireshark查看TCP三次握手四次挥手
② WireShark抓取TCP四次挥手报文实战 -
一查,发现网上好多人都有和我一样的情况,原来是:
服务器在确认的同时也提出要释放连接,因此将确认和释放连接合并到一起进行发送。 -
教科书式的四次挥手,更多的是:
① 服务器收到客户端释放连接的请求时,还需要向客户端发送数据,因此服务器只进行确认。
② 当服务器的数据发送完成后,它再向客户端发送释放连接请求。