【JaveEE】UDP 与 TCP 原理

简介: 1. 应用层协议(自定义组织格式) 对应后面的一个章节HTTP协议,应用层的代表协议,到时候重点讲解

JaveEE & UDP 与 TCP 原理


1. 应用层协议(自定义组织格式)


   对应后面的一个章节HTTP协议,应用层的代表协议,到时候重点讲解


而大多数时候,都是程序员自定义组织的协议~



   而字段与字段之间如何组织呢?


约定:


   传输哪些数据

       按甲方爸爸的需求以及实际需要的

   组织格式

       随意约定


常见组织格式:


   分隔符

       以空格、回车…分割

       以分号…表示结束


实际开发会使用一些现成的格式:


   xml(基本认识)

       html是特殊的xml格式

       html标签名和含义都是固定的,是我们需要遵守的


标签的形式:< XXX > … </ XXX>



   json(基本认识)


   以{ }作为标识


   内部有多个键值对,每个键值对之间用逗号分割


   key与值之间使用冒号分割

       key必须是字符串,

       值可以是数组,字符串,数字甚至是另一个json

2. 传输层UDP协议


   柿子要挑软的捏~


2.1 数据报报文格式



   这是教科书上的画法~


其实并不准确,真实的报文应该是这样的:

2.1.1 源端口与目的端口




可能有人会想,服务器不是远在天边的“服务我们的机器”吗?


   然而并不绝对,一些服务器可以是我们本地主机上的一个程序

       例如http或者mysql


http有个专属“座位“:80


   ssh:22

   ftp:21

   …

   “端口0”并不正式存在。 它被定义为无效的端口号。


并不是说这些端口号就代表了“远方服务器”的位置!


   端口号:主机上程序的位置!


至于“专属座位”有什么用


   服务器一般端口号不需要怎么改变,所以保持在一个端口号是个正常的抉择

   不然每次你都要去查这个常用的服务器端口号是多少~


2.1.2 报文长度和校验和



报文长度:0~65535 => 64KB(64KB - 1B,近似64KB)


   代表UDP正文最大就是64KB大而已

   不是说只能传一个“65535”大小的整数~

   而是65535字节的数据量!


时代不同,现在64KB很小了,一个表情包都能几MB了~


   但是如果要扩大这个限制,那么我们就要升级UDP系统

   只有都升级,才能通讯,这不现实~


要传输大数据


   把数据拆分为多个数据,用多个UDP数据报传输~

   不用UDP,用TCP去传输 > v o

       TCP就没有限制


所以,UDP的数据报不宜过长,否则会出错


校验和:


   我们传递的数据本质是01…,而我们用高低电平表示01



   难免会有一些干扰,例如强磁场(太阳黑子)

       这样就会导致一些高电平转变为低电平,低电平转变为高电平



   那么校验和的存在,就相当于定下了一个标准

       满足这个标准,数据不一定对;但是不满足这个标准,这个数据肯定错

   而这个校验和,要是中间数据发生01转变,大概率是对不上的

       可能校验和跟数据发生突变后,还对上了。很极端的情况

   例如:

       小马去太空,原本五根手指,回来变成四根,”校验和为5根手指“,这样就对不上了~

       回来还是五根,但是细节不对,但是的但是蒙混过关了~

       校验和突变为“4根手指”,反而对上了(极端)


校验和是通过复杂计算后的一个数值~


   发送方:



   接收方:



   有很多种方式,例如CRC算法,奇偶校验…

   对不上就数据就一定不正确!


通过上述结构,也可以看出UDP并不在意数据传输是否成功~


   但是却有校验和校验数据正确性 > v <


3. 传输层TCP协议


核心机制,在于接收方收到了或者没有收到,都会有个应答,对传输失败有所动作


   教人知识也是如此,我如果教一个同学一个知识,他没有如何应答,我就没法判断他掌握了没有~

       会了:我继续讲~

       不会:我重新讲~


数据报报文结构:


3.1 TCP是如何保证可靠传输 — 确认应答


可靠性不等于安全性


   安全性是指容不容易被黑客篡改 / 窃取

   可靠性是指数据传输是否能正确到达对方


应答报文规则:


   单条信息发送:

       发送方没收到应答是不会继续发消息的


   多条信息发送:

       socket里有个接受缓冲区,里面就会把序列排好,再被接收方读取~



   应答报文的区分

       后面ACK代表的就是应答报文ACK

3.2 应答报文ACK的作用


3.2.1 丢包


丢包在互联网里是一个很普遍的现象


   丢包的原因:信息在互联网中传输,要经过很多交换机和路由器,任何一个节点出现问题,都有可能会导致丢包

   网不好:ping、延时、丢包率高…

       每个设备都承担很多转发的任务

       每个设备转发能力有限

       某一时刻某个设备,流量达到峰值,就可能导致那一刻的数据被丢包!



   非常容易出现概率性丢包!

       一般只会丢一些

   打游戏(对抗性)出现丢包,体验感会很差


丢包率如果达到10%,你基本上已经玩不了游戏了

3.2.1 处理丢包现象 — 超时重传


如果发送方在一段时间后,迟迟没收到ACK,则发送方会判定为刚才的数据丢包了!


   发送方就会重新再发一遍,即 超时重传

   大概率重新发过去是能成功的,如果又失败了,超时重传即可


例如丢包率为10% ==> 丢包三次 0.1%,概率很低很低了,如果还丢包,那网络出现问题的概率更大!


   丢包很多次 ==> 丢包率50% + ,这就太离谱了


所以,TCP处理这种多个包丢失的情况,仍然会超时重传


   但是,每丢包异常,超时等待时间就会变长

   但是的但是,如果连续丢包很多次,多半是你网络出现严重问题了,TCP将尝试重连

       如果重连都失效,TCP就会关闭连接,放弃此次网络通讯


其实没有收到ACK有两种情况:


   数据丢了当然就没有ACK

   接收方收到数据了,但是发出ACK丢了

       发送方是区分不了这种情况的,一定会超时重传

       这样的话,接收方将收到重复的一个数据

       这很严重,要是是涉及钱的操作,重复扣款两次,那就糟糕了!


还记得TCP的序号机制吗


   TCP会根据发过来的数据的序号,自动去重!

   保证应用程序读到的数据仍然只有一份


TCP太伟大了,T.T


   确认应答,保证可靠性

   超时重传,弥补丢包现象


   这两个机制就是TCP的基石~


3.3 连接管理


问:TCP是如何实现可靠性的?


   正确答案:确认应答 + 超时重传

   误解:三次握手,四次挥手


但是,可靠性跟三次握手和四次挥手是有一点点关系的


   但是的但是,可靠性要由确认应答和超时重传严密细节地实现

       而三次握手和四次挥手只是保证“连接了”的这个前提罢了


3.3.1 TCP建立连接 — 三次握手


   一次握手 (handshake):一次交互


三次握手表示客户端和服务器之间,通过三次交互,建立了连接关系


   连接:双方各自记录对方的信息

   客户端发出请求连接的申请 【syn】

   服务器返回 【ack】 确认连接

       并发送 【syn】,申请与客户端连接

   客户端也返回 【ack】 确认连接


小例子,小马和老马语音聊天:


   小马问:你那边听得到我的声音吗?

   老马说:听得到

       你呢?

   小马说:我也听得到


如果老马不问,老马就不知道小马听不听得到它的声音


就是这个道理


   客户端申请并要求服务器 “接受我的端请求和返回给我的响应”


   服务器回复ack就相当于接受连接,承诺接受客户端请求和返回响应

       服务器也要申请并要求客户端 “发送给我请求和接受我的响应”


   客户端回复ack就相当于接受连接,承诺发送给服务器请求和接受服务器的响应


这合乎常理,发送申请不代表我已经连接到他了,只是试探,而对方接受申请则是肯定接受我的连接(go!我答应干活了)了,对方也要发送个申请来连接我,我再接受他的连接,才算是真正的“连接”(试探成功,我也要努力干活)


而服务器的ack和syn合成一个数据报一起发送,这是合理省事的,因为在双方未正式连接完之前,服务器也不需要做啥,一起发送是才是个明智的选择


   见以下数据报报文结构分析


3.2.2 报文中特殊的六个比特位



   普通的数据报这六位都是0,但是如果出现1,就代表特殊的含义~


第二位为1:ack报文 ==> 应答报文


第五位为1:syn报文 ==> 同步报文


第二位和第五位都为1:ack + syn报文


   这就是三次握手的第二次握手发送的报文


第六位为1:fin报文 ==> 结束报文


其他几个不讲~


   见四次挥手


为什么三次握手:


   投石问路,验证客户端和服务器的发送能力与接受能力是否正常

       但是没有测“功底”

   投石问路,建立可靠传输的基础,但是不是远远达不到“严密保证”的作用的


3.3.3 TCP断开连接 — 四次挥手


   跟三次握手很像,但是有点差异

       主要是因为断开连接,要保证服务器那个线程的活要干完~


一样的:


   客户端:“你可以断开连接吗”

   服务器:“ok”

       干完活后:“你也断开连接吧”

   客户端:“ok”


一般来说,服务器那个线程是不会立马结束的,所以ack和fin分两次发


   但是也有个别情况,ack和fin,应答报文和结束报文是同一个数据报发送

总流程:

3.4 TCP是如何挽救效率的


TCP为了可靠性,牺牲了效率


   因为要等待应答,超时重传…


单看效率,是完全比不上UDP的


   但是TCP也在挽救它的效率~


3.4.1 批量发送 — 滑动窗口


   减少等待应答的次数


批量发送:一次发多条数据,同时等待一个ack

批量发送不是无限制发送数据,而是发送到一定程度后,等待ack


   发太多对方也可能受不了


而这个限制就是窗口的大小~


   这就相当于用一单位的时间,去等待四单位的ack

       微观上看,每次窗口内部,都是同时在等的

       宏观上看,近似没等一单位时间,窗口快速滑动,四个数据几乎同时收到ack


动图演示:


   按序号处理后每返回一个ack,窗口滑动

   发送方立即发出新窗口内的新来的那条数据,立马发送


滑动窗口的丢包现象处理模式:


   可靠性重要程度肯定要大于效率

       不能为了效率而降低可靠性


   ack丢失


这种情况,完全没有影响,因为应答报文有个应答序号,其含义是其之前的数据都正常读到


   那么一个ack就可以代表其之前的所有ack

   那么最后的ack没了咋办,超时重传 ==> 缓冲区去重,接收方重新发ack


动图演示:


   中途没滑的,后面一次性滑过去


   数据包丢失

       1001-2000的数据丢失,那么主机B就一直发的是应答序号为1001的应答报文,去索要1001开头的数据

           收到了2001-7000的数据,但是应答的还是1001

           2001-7000在缓冲区里呆着呢

       到达一定次数后/超时重传,机器A重新发送1001-2000的数据

           处理完1001-2000的数据以及早就收到了的2001-7000的数据后,发出7001的ack



动图演示:


   这个重传过程没有任何冗余操作,整体效率很高,也被称为“快速重传”



而,如果批量发送太多,挤爆了缓冲区怎么办?


   “流量控制”


3.4.2 流量控制


流量控制就是在批量发送的时候,限制滑动窗口的大小,不能导致接收方的缓冲区炸了


窗口越大 ==> 速度越快 ==> 更容易让缓冲区炸


   缓冲区炸了,多余的数据全部丢包!在这里插入图片描述


   所以流量控制能够保证一定的可靠性


机制:


   发送一小批的数据去试探

   返回的ack,传递了一个信息,“窗口大小”的字段:

       这里的值就是,建议发送方发送的窗口大小

       计算这个窗口大小的方法很简单粗暴,缓冲区剩多少就是多少




此图的动图表示为:


   如果窗口大小为0,就需要再一个ack去告诉他位置腾出来了

       socket读数据消费缓冲区的内容

       等待等待等待~

       有点类似阻塞队列

   但是时时等不到,所以超时重传(窗口探测) — 4001-4001


但是实际上,实际的限制的窗口大小不等于缓冲区剩余的空间大小


   这也是为什么刚才说是“建议”


真正的滑动窗口大小 = f ( 流量控制, 拥塞控制 )

3.4.3 拥塞控制


流量控制:


   衡量了接收方的处理能力


拥塞控制:


   衡量路径上的处理能力


我们知道,数据在互联网的传输路径上,会经过很多个路由器和交换机


   那么,只要中间一个设备承受不了这个流量,那么就会导致不可靠传输,即丢包



就像耳熟能详的“木桶效应”:



真正的滑动窗口大小,应该是通过综合考虑到接收方缓冲区剩余空间,中间路径节点的个数和承受能力。


   并且,每次传输数据也不一定是按照刚才的路径去传输的,所以无法准确得出数值


最好的方法就是:实验practice,实践出真理,通过实验找到一个合适的发送速率。


   一开始的时候按照小速率发送,如果不丢包(丢包一律视为承受能力不足),就可以提高一下速率(扩大窗口大小)

   提高提高提高

   直到丢包了,把窗口调小

       有确认应答和超时重传处理丢了的包

   重复上述过程


   处于动态平衡的过程



   指数增长快速到达ssthresh(阈值)后,加法增长稳步上升(减少丢包率)

   丢包后,重新去做实验,并且ssthresh阈值更新(变大 / 变小 /不变)



拥塞窗口:


   拥塞控制实验出来的窗口


实际窗口就是:min{拥塞窗口, 流量窗口}

3.4.4 延时应答


TCP的可靠性核心为:确认应答


   ACK要发,但是不是立即发,而是等一小会儿再发~


但是通过刚才对TCP的了解,决定传输效率的关键因素为“窗口大小”


实际窗口就是:min{拥塞窗口, 流量窗口}


   要是你ack立马发过去,那就有数据立马发过来,那么就相当于传输过来的数据又多了,可能会导致窗口变小~


相当于说:


别人发任务给我,我完成了一部分,不立马说我完成了一部分(那么它就会给我补一点任务),而是完成百分之70后才跟他说,这样压力就少很多~


这个ack延时发送后,窗口大小大概率是变大了的,因为这个过程里,接受方一直消耗接受缓冲区里的内容~


       数量控制:每隔N个包就应答一次

       时间控制:超过最大延时时间就应答一次


看情况处理,也有一些包是不会延时的

3.4.5 捎带应答


   基于延时应答


客户端服务器之间的通信,一般是 “一问一答” 的模式


   上传大文件的时候,可能就会分为多个包请求,即 “多问一答”

   下载大文件的时候,可能就会分为多个包响应,即 “一问多答”

   “多问多答”,游戏串流~(streamlink / moonlight)

       pc成为服务器,手机成为客户端

       手机一系列请求给pc,pc返回一系列响应

       复杂,并不是一条对着一条的~


对于一问一答的形式:



ack原本是立马返回的,但是结合延时应答,如果延时应答过程中,响应计算好了,或者时机很接近,那么ack就和响应一起打包发送,这就是捎带应答


   合成一个比分两次发,效率更高


所以说,四次挥手有时可能是三次挥完呢?


   原因就是延时应答,捎带应答


3.5 面向字节流


   多个TCP的数据报,在接收方接收缓冲区里,被拆分为应用层数据报,紧紧挨着,那么就会出现“粘包问题”


   我们分不清这三个请求哪跟哪的~


定义报与报之间的分割符,这就是一个有效方案


   这里,我们就可以定义,说完话要加句号或者问号~


还有一个常见方案:约定数据的前4个字节(或者更多),表示整个数据报的长度


   这些都是应用层数据报协议的注意事项~

   协议里会提到报的数据格式,和报的边界


3.6 异常情况


3.6.1 进程关闭 / 进程崩溃


   进程没了,socket文件关闭(发出fin),连接还在,四次挥手正常进行

   主机还醒着,就可以回应ack


3.6.2 主机关机(正常流程关机)


   杀死所有用户进程 ==> 进程没了

       socket文件关闭(发出fin),连接还在,四次挥手正常进行

       主机还醒着,就可以回应ack

   如果四次挥手没挥完,对方就会重传fin,多次无果重置连接,再不行就释放连接了


3.6.3 主机掉电(因为电的原因强制快速关机)


   肯定来不及做任何挥手操作


   对方是发送方,对方就会收不到ack ==> 超时重传 ==> 重置连接 ==> 释放连接


   对方是接收方,对方是没法立即知道,我这边是没来来得及发新的数据,还是我“死了”


       我可能在控制台输入中呢~


       TCP内置了心跳包的“保活机制”

       周期性

       如果心跳没了,你就是“死了”


就是说,对方是接收方,对方就会定期给我发一个心跳包(ping),我就返回一个(pong)


   如果每个ping,都有即使的pong,那么就说明我“没死”,机器良好

       我如果在控制台输入中或者等等情况下,机器正常,就会收到ping,返回pong,这个不需要代码控制

   如果ping没收到pong,超时重传 ==> 重载连接 ==> 释放连接


例子:


   我设置了一个炸弹,我如果死了,炸弹就会爆炸。炸弹每一段时间就会发送给我手腕上的手表一个ping,如果我有脉搏,手表就会返回一个pong,如果我死了,就不会有pong,炸弹就会爆炸。


3.6.4 网线断开


   来不及任何的挥手操作,跟第三点是一样的


4. TCP十大核心机制小节


   确认应答

   超时重传

   连接管理

   滑动窗口

   流量控制

   拥塞控制

   延时应答

   捎带应答

   面向字节流

       粘包问题

   异常处理

       心跳包


更多TCP的细节,可以查看这个标准文档:


RFC 9293: Transmission Control Protocol (TCP) (ietf.org)

5. TCP 与 UDP的差别


TCP 可靠传输,效率没那么高,UDP不可靠传输,效率高~


两者的不同在于应用场景的不同


   绝大多数情况下,都可以使用TCP

   但是对于一些要求高效率,对可靠性要求不高的情况下,UDP会更好

       例如,机房内部的内网之间的数据传输 / 分布式系统~


场景:既需要可靠性,又需要比较高的效率

   这两种协议都不合适,而传输层协议当然不止有这两种,如果你感兴趣的话,可以去了解哪些协议更适合处理这样的场景


相关实践学习
容器服务Serverless版ACK Serverless 快速入门:在线魔方应用部署和监控
通过本实验,您将了解到容器服务Serverless版ACK Serverless 的基本产品能力,即可以实现快速部署一个在线魔方应用,并借助阿里云容器服务成熟的产品生态,实现在线应用的企业级监控,提升应用稳定性。
云原生实践公开课
课程大纲 开篇:如何学习并实践云原生技术 基础篇: 5 步上手 Kubernetes 进阶篇:生产环境下的 K8s 实践 相关的阿里云产品:容器服务&nbsp;ACK 容器服务&nbsp;Kubernetes&nbsp;版(简称&nbsp;ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情:&nbsp;https://www.aliyun.com/product/kubernetes
相关文章
|
1月前
|
域名解析 网络协议 关系型数据库
tcp和udp的区别是什么
TCP和UDP是互联网协议中的传输层协议。TCP是面向连接的,通过三次握手建立可靠连接,提供数据顺序和可靠性保证,适用于HTTP、FTP等需要保证数据完整性的应用。UDP则是无连接的,数据报独立发送,传输速度快但不保证可靠性,常用于实时通信、流媒体和DNS解析等对速度要求高的场景。根据应用需求选择合适的协议至关重要。
tcp和udp的区别是什么
|
1月前
|
网络协议 网络性能优化
认识TCP和UDP的区别
重排机制:由于UDP数据包可能因网络原因而发生乱序,因此在应用层需要对接收到的数据包进行排序。
31 4
|
1天前
|
网络协议 安全 网络性能优化
CCNA 200-301系列:TCP和UDP简介
【4月更文挑战第21天】
14 8
|
1天前
|
缓存 网络协议 安全
TCP和UDP 传输层协议的区别
TCP协议全称是传输控制协议是一种面向连接的、可靠的、基于字节流的传输层通信协议。
7 2
|
3天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
1月前
|
网络协议 网络性能优化
网络面试题:TCP和UDP的区别
网络面试题:TCP和UDP的区别
25 0
|
1月前
|
网络协议 Python
Python网络编程实现TCP和UDP连接
Python网络编程实现TCP和UDP连接
30 0
|
1月前
|
网络协议 网络性能优化 Python
python怎么实现tcp和udp连接
python怎么实现tcp和udp连接
16 0
|
1月前
|
网络协议 Linux
TCP 和 UDP 的 Socket 调用
【2月更文挑战第19天】
TCP 和 UDP 的 Socket 调用
|
1月前
|
网络协议 数据格式