当前位置: 首页 > news >正文

网络编程(二)TCP和UDP

认识UDP和TCP

         TCP和UDP都是传输层中最经典的协议,传输层重点关注是将数据从发送端传输到接受端 ,二者都是全双工(一条链路能够进行双向通信)

UDP

协议端格式: 

源/目的端口号:从发送端(源端口号)——>接收端(目的端口号)

注:16位UDP长度代表整个数据报的最大长度(UDP首部+数据),如果校验和出错会直接丢弃

UDP的首部为16位,也就是说UDP传输的数据最大长度为64K, 如果传输的数据>64k就需要在应用层手动分包,多次发送,然后在接收端拼装(数据太大了,只能分几次发了)

特点:

        无连接:不需要建立连接,只需要知道接收端的端口号和IP就能够进行传输

        不可靠传输:没有确认机制,没有重传机制(丢了就是丢了,没有售后),即使是因为网络故障导致也不会有任何的错误信息返回

        面向数据报:不能够灵活的控制读写数据的次数和数量,每次读写操作的执行对象必须是一个完整的UDP数据报


 TCP

协议端格式:

SYN:请求建立连接,携带SYN标识的称为同步报文段

ACK:确认号是否有效(由服务器接收到客户端发送请求连接之后将同步报文段加上ACK发送给客户端)

FIN:通知接收端,发送端要关闭连接(携带FIN标识的称为结束报文段

RST:请求重新建立连接(携带RST标识的称为复位报文段

PSH:提示接收端应用从TCP缓冲区把数据读走

URG:紧急指针是否有效

特点:

        有连接:TCP传输首先需要与服务器建立连接,再根据接收端的端口号和IP向接收端进行传输        

        可靠传输:TCP传输有确认应答机制,如果传输数据没有被接收端获取到,那么TCP就会重新进行传输(有售后)

        面向字节流:读写操作灵活(例如文件操作也是字节流)


 理解TCP协议的状态转化:

确认应答

TCP会给每个字节进行编号,也就是序列号,而每一个ACK也都带有对应的确认序列号,接收端通

过ACK的确认序列号来向发送端反映已经收到的数据

数据序列号意义:

1.能够通过序列号来匹配正确应答(因为网络编译会有“后发先至”的特性,通过序列号可以匹配到对应序列号的应答)

2.确认数据是否成功传输到对端


 连接管理(三次握手建立连接,四次挥手断开连接)

三次握手(建立连接) 

过程:客户端向服务器发送同步报文(SYN),服务器接收到之后加上应答报文(ACK)组成一个网络数据一起返回给客户端,客户端接收到网络数据之后给服务器发送应答报文(ACK)结束。 

  

三次握手(建立连接)的意义:

确定双方通信链路是正常的,才能进行数据传输 

四次挥手(断开连接):

四次挥手的意义是告知对方,要终结此次连接,而提出断开连接的可以是客户端、服务端中的任意一方 

过程:

第一次:客户端 ——>服务端:客户端发送FIN,告知服务端我要断开连接了,此时客户端已经没有数据要传输,服务端还可以接受数据(客户端establish——>FIN_wait1)

第二次:服务端——>客户端:服务端向客户端发送ACK,表示ojbk,我现在处理的数据编号是xxx,还有数据没有处理完(服务器从establish——>close_wait,客户端收到ACK变成FIN_wait2)

第三次:服务端——>客户端:服务端向客户端发送FIN,表示我处理完所有数据了,我也断开连接了(此时服务端close_wait——>last_wait,客户端收到FIN,从FIN_wait2——>time_wait)

第四次:客户端——>服务端:客户端向服务端发送ACK,表示知道了,双方都关闭,一方不再传输数据,一方不再接收数据


超时重传

在一定的时间内用来应对网络故障导致丢包的策略,发送端总是通过确认应答来验证数据是否传输到对端

可能情景:

①数据包传输的时候丢了,对端没接收到

②对端接收到之后,给发送端发送的确认号丢了(ACK丢了)

对于第二种情景,重传之后对端会接收到两份相同的数据,这时候TCP会对对端的数据进行去重操作(例如转账这种情景,发送重复转账那就是非常严重的错误!!) 

超时重传的超时时间是否是具体化的?

不是,超时时间是随着重传轮数增加,第一次重传是50ms之后,没有接收到确认应答进行第二次重传,第二次重传可能是100ms,依次类推。


滑动窗口

动态调节传输效率:由于是全双工模式,所以滑动窗口适用于双端的数据传输

窗口的大小决定了数据的传输速率,假定客户端作为传输端,服务端作为接受端,接收端规定自身接受数据的窗口大小,然后传输端根据接收端的窗口大小来调节传输端的窗口大小

就好比,你接收端说我的快递柜只有四格,那传输端看你只有四个格子(窗口大小),每次只拿四个快递(数据),然后传输端把编号为1和2的快递发给接收端,接收端拿到了之后放到快递柜里,只有在接收端把1和2号快递从快递柜上拿走数据处理),传输端在接收端收到1和2号快递之后会更新最新的快递编号为3和4,并且把放在地上的5和6号快递补上来(因为窗口大小为4) 


流量控制

流量控制就是控制数据传输的速率,防止因为传输速率过快导致缓存区溢出

假定缓冲区大小是500,里面有接受未处理的数据占了300,此时因为传输速率过快导致有300的数据要传输给缓存区,缓存区的空间只有500-300=200,那就会有大小为100的数据被丢弃,触发重传机制,而这部分重传的数据只有等到缓存区释放出空间才会进行重传~

传输数据的时候,传输端的速率会根据窗口大小来调整,当缓存区已经满了的情况下窗口会被调整为0,不再传输数据直到缓存区释放空间 


拥塞控制

这里要有一个概念,就是拥塞窗口。传输端传输数据是一个慢启动的过程,通常会先传输少量的数据试探当前的网络状况,每次传输成功之后就会扩大窗口大小,提高传输速率,遇到拥塞情况就匀速传输(不再倍速提高速率,呈线性增长),具有快重传、快恢复特性


延迟应答、捎带应答

延迟应答——接收端在收到一定的数据量才向传输端返回接收标识(ACK)

例如:传输端发10个数据,接受端每收到1个就要返回一次ACK告知传输端数据已经被接收,延迟应答就是改成每收到5个数据向传输端反馈,只需要反馈2次

延迟应答核心机制:

时间阈值:在一定的时间内没有数据交互就向传输端发送ACK包

数据阈值:每当接受端收到一定量的数据就会向传输端发送ACK包

避免超时:延迟应答的时间间隔不能超过或等于重传机制时长,超过这个时长会导致数据重传


 捎带应答——接收端需要向发送端传输数据时,将ACK捎带在数据报文里,不需要单独传输ACK包

TCP面向字节流,粘包问题和解决方案

面向字节流:在使用TCP协议进行传输数据时,可以灵活读写,例如1个100字节长度的数据,可以利用TCP协议进行读写,1次读写100个字节长度/1次读写1个字节长度然后执行100次读写操作

“粘包问题”:

这里的包针对的是应用层的数据包,数据包通过TCP协议传输到达的时候,应用层不知道具体数据长度,只识别到数据包有序列号,应用层看到的是一大串的字节数据(就是若干数据包紧挨着,但是你不知道这些数据包的界限在哪?那应用层怎么读取具体的数据?)

在这一点上,UDP和TCP就有所区别,UDP由于是传输数据报,数据报有报文长度,而TCP用的是序列号

解决方案:确定数据包之间的边界

①对于定长的数据包,每次在进行读写操作的时候保证进行定长读取

②对于定长的数据包,在数据包的头部规定一个统计数据包总长的字段,这样每次读写就能知道数据包的结束点位

③对于边长的数据包,还可以在包与包之间用规定好的符号进行分割(不过这个需要程序员自行在应用层进行规定)

基于UDP实现可靠传输:

1.引入序列号,保证数据顺序;

2引入确认应答机制,保证对端接收到了数据;

3.引入超时重传,在一定时间内没有收到应答就重新传输

MTU对UDP和TCP的影响:

MTU对于数据片的最大传输单元是1500个字节,最小是46个传输字节(除去报头)

而UDP传输的数据报又不是定长的,如果数据包长度过大,需要进行数据分片,那么就会大大增加丢包的情况,导致收到的数据不完整,而且分片过后有一个包会没有ip报头

TCP面向字节流传输,如果遇到需要IP分片的情况,由于TCP的可靠传输机制,服务端会通过匹配序列号来确认数据是否传输到达,而服务端匹配的序列号如果不是对应的序列号就会让整段数据重传(例如:传输的数据段序列号是1-1000,然后由于分片变成了460和540,服务端先后接收到460和540然后进行匹配,因为要匹配的序列号应该是1000,所以服务端让客户端重新传输1-1000这个数据段,然后服务端再对受到的数据进行去重)

http://www.dtcms.com/a/267758.html

相关文章:

  • BM6 判断链表中是否有环(牛客)
  • 2025年- H92-Lc200-- 64.最小路径和(多维动态规划)--Java版
  • 详解存储单位、内存寻址及数据存储方式
  • Feign调用报“请求方法POST不支持“错误
  • WPF学习笔记(25)MVVM框架与项目实例
  • 基于pcl点云库实现激光雷达数据采集
  • java整合itext pdf实现自定义PDF文件格式导出
  • 调参——optuna
  • Python 面向对象编程(OOP)全面详解:类、对象与 API
  • 【算法刷题记录(简单题)002】字符串字符匹配(java代码实现)
  • 线程池的七个参数设计源于对高并发场景下资源管理、系统稳定性与性能平衡的深刻洞察
  • Policy Gradient【强化学习的数学原理】
  • 【C语言刷题】第十一天:加量加餐继续,代码题训练,融会贯通IO模式
  • JMM--数据原子操作
  • Python asyncio库与GIL之间的关系,是否能够解决核心问题?
  • Spring--循环依赖以及三级缓存详解
  • Linux安装java后没法运行
  • 计算机组成原理《浮点数的存储》
  • Python基础之字典(Dictionary)全面指南
  • 南山科技园的步行
  • Qt项目锻炼——TODO清单(三)
  • 【论文笔记】OctoThinker:突破 Llama 推理瓶颈的中期训练范式
  • 乌邦图(20.04)添加中文拼音(中文输入法)
  • 实现电池储能装置的双向DCDC
  • Qt项目锻炼——TODO清单(二)
  • jmm--volatile
  • 前端面试专栏-算法篇:18. 查找算法(二分查找、哈希查找)
  • vue3 el-input el-select 非空校验
  • 大数据学习2:HIve
  • Linux进程管理:从基础到实战