TCP与UDP协议

TCP协议

传输协议TCP简介

  • 面向连接,可靠的,基于字节流的传输层通信协议
  • 将应用层的数据流分割成报文段并发送给目标节点的TCP层
  • 数据包都有序号,对方收到则发送ACK确认,未收到则重传
  • 使用校验和来检验数据在传输过程中是否有误

TCP报文头

TCP与UDP协议

  • Source Port和Destination Port: 分别代表源端口(2B)和目的端口(2B)
  • Sequence Number(seq): 占用4B,tcp字节流中每个字节都是按顺序去编号额,例如一个报文的序号字段值为107而携带的数据共有100个B(字段),如果有下一个报文段就应该由107+100即207开始
  • acknowledge numbe: 占4B,期望收到对方下一个报文的第一个数据字节的序号,例: B 收到了A发送过来的报文,其序列号字段为301而数据长度是200字节,这表明B正确的收到了到序号301+200-1=500为止的数据,因此B期望收到A的下一个数据序号是501所以B在发送给A的确认报文中会把ack确认号置为501
  • offset: 指出tcp报文的数据距离tcp报文的起始处有多远
  • reserved: 保留域,保留今后使用的,但是目前都会标志为0
  • tcp flag: 控制位,主要由8个标志位组成,每个标志位表示一次控制功能
  • widow窗口: 指的是滑动窗口大小,用来告知接收端与发送端的缓存大小,以此控制发送端发送数据的速率从而达到流量控制
  • check sum: 校验和,指的是奇偶校验,此校验和是对整个pct报文段,包括tcp头部,和tcp数据,以16位进行计算所得,由发送端计算和存储并由接收端进行验证
  • urgent pointer: 紧急指针,只有tcp flags 中的 urg = 1时才有效.指出本报文段段中的紧急字节数
  • TCP option: 可选项其长度可变,定义一些其他的可选参数。

TCP Flags

TCP与UDP协议

urg:紧急指针标志,1 有效,0 忽略。
ack:确认序号标志,1 表示确认号有效,0表示报文中不含确认信息。忽略确认号字段。
psh:push标志,1表示带有push标志的数据,指示接收方在接受到该报文段应尽快将报文段交给应用程序,而不是在缓冲区进行排队。
rst:重置连接标志,用于重置连接,或拒绝连接请求(用于处理连接中断)
syn:同步序号,用于建立连接过程 syn = 1 ack = 0 表示该数据段没有使用稍待的域,则连接应答稍待一个确认则syn=1 ack = 1
fin:finish标志,用于释放连接 1 表示发送方已经没有数据发送了 即关闭本方数据流。

TCP三次握手

当应用程序希望通过tcp与另一个程序通讯时,他会发送一个通信请求,这个请求必须被送到一个确切的地址,当双方握手之后tcp将在两个应用之间建立一个全双工即Full duplex的请求,这个全双工的通讯将占用两个计算机之间的通信线路,知道一方或双方关闭为止.

full duplex: 当A给B发送信息的同时,B也可以给A发送信息.

TCP与UDP协议

各个状态的意义如下:
LISTEN - 侦听来自远方TCP端口的连接请求;
SYN-SENT -在发送连接请求后等待匹配的连接请求;
SYN-RECEIVED - 在收到和发送一个连接请求后等待对连接请求的确认;
ESTABLISHED- 代表一个打开的连接,数据可以传送给用户;

三次握手流程

  • 客户端发送SYN报文段请求连接报文(SYN=1,seq=x),此时客户端处于SYN-SENT,不能携带数据,服务端处于LISTEN;
  • 服务器向客户端发送SYN+ACK报文段报文(SYN=1,ACK=1 ,seq =y,ack=x+1),服务端处于SYN-RECIEVD,客户端处于SYN-SENT;
  • 客户端向服务器发送ACK报文段(ACK=1,seq=x+1,ack=y+1),此时客户端处于ESTABLISHED服务端处于ESTABLISHED

第一次握手:主机A发送位码为SYN=1,随机产生seq number=1234567的数据包到服务器,主机B由SYN=1知道,A要求建立联机;

第二次握手,主机B收到请求后要确认联机信息,向A发送ack number=(主机A的seq+1),SYN=1,ACK=1,随机产生seq number=7654321的包;

第三次握手:主机A收到后检查ack number是否正确,即第一次发送的seq number+1,以及位码ACK是否为1,若正确,主机A会再发送ack number=(主机B的seq+1),ACK=1,主机B收到后确认seq值与ACK=1则连接建立成功。

为什么需要三次握手?

  • 为了初始化Sequence Number的值,在建立连接通信的时候,双方需要互相告知其Sequence Number并发送确认消息,确认双方可以建立连接通信

首次握手存在隐患-----SYN超时

首次握手存在存在SYN超时的问题,Server收到Client的SYN,回复SYN-ACK的时候未收到ACK确认,Server不断重试直至超时,Linux默认5次,总共需要63秒断开连接.

此时即可使用SYN攻击(SYN Flood):建立大量的半状态连接,消耗CPU,内存,主机,路由器,网络资源.

针对SYN Flood的防护措施:

  • SYN队列满后,通过tcp_syncookies参数回发SYN Cookies
  • 若为正常连接则Clinet回发SYN Cookie,直接建立连接

另外针对建立连接后,Client出现故障也有一定的防护措施-----保活机制

  • 向对方发送保活探测密文,如果未收到响应则继续发送
  • 尝试次数到达keepAliveTime,仍未收到响应则中断连接

keepAliveTime:保活时间,用于测试连接在时间周期内是否活跃

TCP的滑窗

这里提供一个动态演示的链接

https://media.pearsoncmg.com/aw/ecs_kurose_compnetwork_7/cw/content/interactiveanimations/selective-repeat-protocol/index.html

RTT:发送一个数据包到收到对应的ack,所花费的时间
RTO:重传间隔,定时器时间,如果回复了ack定时器失效,如果没有回复,RTO定时器的时间到了就重传,RTO是通过RTT计算出来的

TCP使用滑动窗口做流量控制与乱序重排

  • 保证TCP的可靠性
  • 保证TCP的流控特性

TCP与UDP协议

图示两个条框即发送端与接收端的缓冲区,都统一看作“从左往右”发送数据(写入缓冲区)或接受数据(从缓冲区读取)。
LastByteWritten指上层应用最新写入缓冲区要发送字节的位置
LastByteAcked指向收到的连续最大ack的位置(从最左端到此是已发送并收到回执的位置)
LastByteSent指向已发送的最后一个字节位置
LastByteRead指上层应用已读取接收的最后一个字节位置(已发送ACK回执)
LastByteExpected指已收到的连续最大的sequence的位置但还没发送回执
LastByteRcvd指已收到的最后一个字节的位置

还能够接受的窗口大小:AdvertisedWindow
还需要发送的窗口大小:EffectiveWindow

TCP与UDP协议

TCP与UDP协议
TCP滑窗可靠性,建立在确认重传基础上
发送方只有收到本段发送滑窗的ACK确认,才移动滑窗左边界
接收方只有在收到的数据ACK之后,才会移动滑窗左边界

接收方前面收到的数据未ACK,后面收到数据,不移动滑窗
确保发送放重传后面的数据。

滑窗大小可动态调整

TCP四次挥手

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KLny5L14-1643873617976)(D:\Note\详解\计算机网络\02.assets\image-20220203142147829.png)]

挥手过程:

TCP 终止连接的四次挥手:

第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进去FIN_WAIT_1状态
第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1,Server进入CLOSE_WAIT状态
第三次挥手:Server发送一个FIN用来关闭Server到Client的数据传送,Server进入LAST_ACK状态
第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手

为什么需要四次挥手才能断开连接呢?

原因:因为TCP是全双工的,所以发送方和接收方都需要FIN报文和ACK报文。即发送方和接收方各自两次挥手即可。只不过一方是被动,所以看上去像四次挥手。

为什么会有TIME_WAIT状态?

原因:

  • 确保有足够的时间让对放收到ACK包(如果被动关闭那方没收收到ACK,就会触发被动端重发FIN包,一来一去正好是两个msl)
  • 有足够的时间让这个链接不会跟后面的连接混在一起。

为啥出现大量CLOSE_WAIT状态的原因?

原因:

  • 对方关闭socket连接,我方忙于读或写,没有及时关闭连接
  • 服务端收到客户端关闭请求,但未响应给客户端。
  • 服务端有资源未释放,或者配置中线程池,连接数原因

**解决方式:**检查代码(释放资源的代码)和检查配置(处理请求的线程配置)

Linux查看服务器连接数命令:

netstat -n | awk '/^tcp/{++S[$NF]}END{for(a in S) print a,S[a]}'

TCP与UDP协议

UDP协议

UDP报文结构

TCP与UDP协议

1.source port 源端口
2.destination port 目标端口
3.length 数据包长度
4.checknumber校验值
5.data数据包

UDP的特点:

  1. 面向非连接
  2. 不维护连接状态,支持同时向多个客户机传输相同的消息
  3. 数据报头只有8个字节,额外开销较小
  4. 吞吐量只受数据生成效率,传输速率以及机器性能
  5. 不需要维持复杂的链接状态表。尽可能保证交付
  6. 面向报文,不对其报文进行拆分或合并,只负责获取

TCP和UDP的区别

  • 面向连接vs无连接: tcp面向连接有三次握手的连接过程,udp无连接适合消息的多播发布,单个点向多个点传输
  • 可靠性: tcp可靠(握手、确认、重传机制),udp不可靠
  • 有序性: tcp利用序列号保证消息的顺序交互
  • 速度: tcp速度慢,因为要创建连接,保证消息的可靠性和有序性
  • 量级: tcp重量级,体现在元数据的头tcp20字节,udp八个字节
上一篇:网络协议实战教程,看这一篇,面试无忧!


下一篇:让创新触手可及,阿里云容器服务 ACK 发行版开放免费下载