网络原理-TCP/IP(5)

TCP协议

延迟应答

它也是基于滑动窗口,提高效率的一种机制,结合滑动窗口以及流量控制,能够以延迟应答ACK的方式,把反馈的窗口,搞大.核心在于允许范围内,让窗口尽可能大.

如果接收数据的主机立刻返回ACK应答,这时候返回的窗口可能比较小.

1.假设接收端缓冲区为1M.一次收到了500K的数据;如果立刻应答,返回的窗口就是500K;

2.但实际上可能处理端处理的速度很快1,10ms之内就把500K数据从缓冲区消费掉了;

3.在这种情况下,接收端处理还远没有到达自己的极限,即使窗口再放大一些,也能处理的过来;

4.如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口就是1M;

简而言之:接受方收到数据之后,不会立即返回ACK.而是稍等一下,等一会再返回ACK.等的这一会,相当于给接收方的应用程序这里,腾出更多的时间,来消费这里的数据.

典型场景:发送方不停发,接收方不停取

新收到的数据也占一部分空间.如果不是立即返回,比如延时100ms,在100ms之内,接收方应用程序就能再多消费一些数据,剩余的空间就更大,返回的窗口就是一个比较大的值. 

一定要记得,窗口越大,网络吞吐量就越大,传输效率就越高.我们的目标就是在保证网络不拥塞的情况下尽可能提高传输效率;

那么所有包都可以延时应答吗?肯定也不是;

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

时间限制:超过最大延迟时间就应答一次;

具体的数量和超时时间,依操作系统不同也有差异;一般N取2,超时时间取200ms;

捎带应答

尽可能把能合并的数据包合并,从而提高效率的效果. 

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是"一发一收"的.意味着客户端给服务器说了"How are you",服务器也会给客户端回一个"Fine, thank you";

那么这个时候ACK就可以搭顺风车,和服务器回应的"Fine, thank you"一起给回客户端.

正常情况下,2和3之间有一定时间间隔,此时就分两个包发送.但是由于延迟应答,ack应答时间有所推迟,ack就可以和response合并.

ack在延时的这段时间里,响应数据刚好准备好了.此时就可以把ack和应答的响应数据合并成一个TCP数据报.本身ack也不携带任何载荷,只是把ACK载荷设置为1,并设置确认序号以及窗口大小.

注意!很多时候客户端和服务端之间是长连接,要进行若干次请求的.在捎带应答的加持下,在捎带应答的加持下,后续每次传输请求响应,都可能触发捎带应答(也不是一定触发,具体是否能触发,取决于代码怎么写,取决于下一个数据来的快不快),都可能把接下来的数据和ack合二为一.

面向字节流

创建一个TCP的socket,同时在内核中创建一个发送缓冲区和一个接收缓冲区

调用write时,数据会先写入发送缓冲区中;

如果发送的字节数太长,会被拆分成多个TCP的数据包发出;

如果发送的字节太短,就会先在缓冲区中等待,等到缓冲区长度差不多了,或者其他合适的时机发送出去;

接收数据的时候,数据也是从网卡的驱动程序到达内核的接收缓冲区;

然后应用程序可以调用read从接收缓冲区拿数据;

另一方面,TCP的一个连接,既有发送缓冲区,也有接收缓冲区,那么对于一个连接,既可以读数据,也可以写数据,这个概念叫全双工;

由于缓冲区的存在,TCP程序的读和写不需要一一匹配,例如:

写100个字节数据时,可以调用一次write写100个字节,也可以调用100个write,每次写一个字节;

读100个字节数据时,也完全不需要考虑写的时候是怎么写的,既可以一次read100个字节,也可以一次read一个字节,重复100次;

粘包问题

在tcp传输的数据到了接收方之后,接收方要根据socket api来read出来.read出来的结果就是应用层数据包.由于整个read过程非常灵活,可能使代码中无法区分出当前的数据从哪到哪是一个完整的数据包.

首先要明确,粘包问题中的"包",是指应用层的数据包;

在TCP协议头中,没有如同UDP一样的"报文长度"这样的字段,但是有一个序号这样的字段;

站在传输层的角度上,TCP是一个一个报文过来的,按照序号排好放在缓冲区中;

站在应用层的角度,看到的只是一串连续的字节数据;

那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分到哪个部分,是一个完整的应用层数据包;

那么如何避免粘包问题呢?归根结底就是一句话,明确两个包之间的边界

对于定长的包,保证每次都按固定的大小读取即可;例如上面的Request结构,是固定大小,那么就从缓冲区从头开始按sizeof(Request)依次读取即可;

对于变长的包,可以在包头的位置,约定一个包总长度的字段,从而就知道了包结束的位置;

对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序员自己来定的,只要保证分隔符不和正文冲突即可);

思考:对于UDP协议来说,是否也存在"粘包问题"呢?

对于UDP,如果还没有上层交付数据,UDP报文长度仍然存在.同时,UDP是一个一个把数据交付给应用层.就有很明确的数据边界.

站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收.不会出现"半个"的情况.

UDP的接收缓冲区不是队列结构,而是链表,每一个结点都是一个UDP数据报.

粘包问题,是TCP引起的,但TCP本身并不解决,而是由程序员写代码自行处理(应用层逻辑),xml,json, protobuffer都能处理粘包问题.

异常情况

进程终止:进程终止会导致释放文件操作符,仍然可以发送FIN,和正常关闭没有什么区别.(进程无论是正常结束,还是异常崩溃,都会触发到回收文件资源,关闭文件这样的效果(系统自动完成的),就会触发四次挥手)

TCP连接的生命周期,可以比进程更长一些.虽然进程已经退出了,但是TCP连接还在,仍然可以继续进行四次挥手.

其中一方机器关机(按照正常流程关机):当有个主机,触发关机操作,就会先强制终止所有的进程(类似于上述的强杀进程),终止进程自然会触发四次挥手~

点了关机之后,此时,四次挥手不一定能挥完,因为系统马上就关闭了.如果挥的快,就能够顺利挥完,此时,本端和对端都能正确删除保存的连接信息.(四次挥手的核心流程)

如果挥的不快,至少也能把第一个FIN发给对端,至少能告诉对方,我这边要结束了.

对端收到FIN之后,对端也要进入释放连接的流程了,返回ACK,并且也发FIN.这里的FIN不会有ACK了,FIN没收到ACK时,势必要进行重传(超时重传的流程中了).

当重传几次后,发现还是不行,还是没有ACK,这个时候就会单方面释放连接信息.

其中一方出现了断电(也算关机,更突然的关机):

(a):断电的是接收方:发送方就会突然发现,没有ACK了,就要重传.重传了几次后,还是不行.

TCP就会尝试复位连接.相当于清除原来的TCP中的各种临时数据重新开始.

需要利用到TCP的"复位报文段"(RST). 但此时的RST也不会有ACK.重置了还不行,单方面放弃连接.

(b):断电的是发送方:这个情况下,接收方需要区分出,发送方是挂了,还是好着暂时没发.

TCP也是如此,接收方一段时间之后,没有收到对方的消息,就会触发"心跳包"来询问对方情况

如果对端没心跳了,此时本端也就会尝试复位并且单方面释放连接了.

TCP/UDP对比

我们说TCP是可靠连接,那么是不是TCP一定优于UDP呢?TCP和UDP之间的优点和缺点,不能简单,绝对的进行比较.

TCP用于可靠传输的场景,应用于文件传输,重要状态更新,数据包很大的传输;(绝大部分场景)

UDP用于高速传输和实时性要求较高的通信领域,例如,早期的QQ,视频传输等.另外UDP可以用于广播;(对于效率要求很高,但对于可靠性不高). 

归根结底,TCP和UDP都是程序员的工具,什么时候用,具体怎么用,还是根据具体场景判定.

 如何用UDP实现可靠传输?

参考TCP可靠性机制,在应用层实现类似逻辑.

例如

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

引入确认应答,确保对端收到了数据;

引入超时重传,如果隔一段时间没有应答,就重发数据.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/251508.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新手小白零基础一分钟自动部署搭建幻兽帕鲁服务器教程

对于初次接触游戏联机服务器搭建的新手玩家来说,部署和配置一个像“幻兽帕鲁”这样的网络游戏联机服务器可能会显得有些复杂。但别担心,本文将提供一种快速、简洁且适合零基础新手的一分钟自动部署搭建幻兽帕鲁游戏联机服务器的详细教程。 本文将为大家提…

Linux 驱动开发基础知识——内核对设备树的处理与使用(十)

个人名片: 🦁作者简介:学生 🐯个人主页:妄北y 🐧个人QQ:2061314755 🐻个人邮箱:2061314755qq.com 🦉个人WeChat:Vir2021GKBS 🐼本文由…

Oracle闪回日志管理(flashbackup log)

Oracle闪回日志管理(flashbackup log) 1.开启闪回日志 shutdown immediate startup mount; alter database archivelog; alter database flashback on; alter database open; 2、查看闪回日志保留期限 show parameter flash 默认是1440分钟&#xff0c…

【LeetCode】刷题总结 - 15. 三数之和

15. 三数之和 | LeetCode 思路 首先对 nums 进行排序,然后设置三个指针:left、mid、right: left 从最左边开始,依次向后遍历每次固定住 left 后,就化为一个 2sum 问题: mid left 1,right …

python中[[]] * (n)和[[] for _ in range(n)]的区别

1、现象 刷leetcode207的时候碰到一个坑,用[[]] * (n)初始化二维数组,逻辑是正确的,但是结果始终不对。 2、原因 最后定位是初始化语句使用错误导致的,我使用的是[[]] * (n),应该使用[[] for _ in range(n)] 3、解…

SpringBoot:实例一

一、实现的效果 在浏览器地址栏输入http://localhost:8080/hello&#xff0c;当前页面显示hello world 实例一代码&#xff1a;点击查看LearnSpringBoot01 点击查看更多的SpringBoot教程 二、 效果图 三、 pom.xml代码 <?xml version"1.0" encoding"UTF-…

【快速上手QT】01-QWidgetQMainWindow QT中的窗口

总所周知&#xff0c;QT是一个跨平台的C图形用户界面应用程序开发框架。它既可以开发GUI程序&#xff0c;也可用于开发非GUI程序&#xff0c;当然我们用到QT就是要做GUI的&#xff0c;所以我们快速上手QT的第一篇博文就讲QT的界面窗口。 我用的IDE是VS2019&#xff0c;使用QTc…

【小白学unity记录】使用unity播放声音

1. 示例 unity中播放声音涉及到两个组件。AudioSource和AudioClip。AudioSource可以理解为播放器&#xff0c;AudioClip可以理解为音频片段文件。AudioSource可以通过.clip属性切换音频片段。 using UnityEngine;public class PlayerController : MonoBehaviour {private int…

Windows11通过Hyper-V创建VM,然后通过vscode连接vm进行开发

这边需要在win11上建立vm来部署docker(这边不能用windows版本的docker destop)&#xff0c;学习了下&#xff0c;记录。 下载系统镜像 首先下载系统镜像&#xff1a;https://releases.ubuntu.com/focal/ 这边使用的是ubuntu20.04.6 LTS (Focal Fossa) &#xff0c;Server inst…

Facebook的数字合作愿景:创新与未来发展

随着科技的飞速发展&#xff0c;Facebook一直处于数字创新的前沿&#xff0c;致力于构建开放、智能、社交的数字社交体验。本文将深入探讨Facebook的数字合作愿景&#xff0c;探索其在创新与未来发展方面的雄心壮志。 引言 在当今数字化时代&#xff0c;社交媒体不仅是人们沟通…

Vue3+vite搭建基础架构(5)--- 使用vue-i18n

Vue3vite搭建基础架构&#xff08;5&#xff09;--- 使用vue-i18n 说明官方文档安装vue-i18n使用vue-i18n测试vue-i18n的国际化配置 说明 这里记录下自己在Vue3vite的项目使用vue-i18n做国际化语言的过程&#xff0c;不使用ts语法&#xff0c;方便以后直接使用。这里承接自己的…

uniapp中配置开发环境和生产环境

uniapp在开发的时候&#xff0c;可以配置多种环境&#xff0c;用于自动切换IP地址&#xff0c;用HBuilder X直接运行的就是开发环境&#xff0c;用HBuilder X发布出来的&#xff0c;就是生产环境。 1.使用HBuilder X创建原生的uniapp程序 选择vue3 2.什么都不改&#xff0c;就…

如何开通GitHub Copilot

GitHub Copilot 是由GitHub 和OpenAI共同开发的人工智能代码辅助工具&#xff0c;可以自动地生成高质量代码片段、上下文信息等。 通过自然语言处理和机器学习技术&#xff0c;能够通过分析程序员编写的代码、注释和上下文信息&#xff0c;自动生成代码&#xff0c;减轻程序员的…

【Springcloud篇】学习笔记十(十七章):Sentinel实现熔断与限流——Hystrix升级

第十七章_Sentinel实现熔断与限流 1.Sentinel介绍 1.1是什么 随着微服务的流行&#xff0c;服务和服务之间的稳定性变得越来越重要。 Sentinel 以流量为切入点&#xff0c;从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。 用来代替Hystrix Sentinel 具有…

NFTScan 与 Merlin Protocol 共同推出 BRC20 Indexer Oracle,于今日正式上线!

近日&#xff0c;NFT 数据基础设施 NFTScan 与 Merlin Protocol 进行战略合作&#xff0c;联合推出了比特币网络原生资产 Indexer Oracle 服务&#xff0c;现在该服务已在 NFTScan 开发者平台上线&#xff0c;任何开发者都可以注册使用&#xff01; Merlin Protocol 是一个专用…

Swift Vapor 教程(查询数据、插入数据)

上一篇简单写了 怎么创建 Swift Vapor 项目以及在开发过程中使用到的软件。 这一篇写一个怎么在创建的项目中创建一个简单的查询数据和插入数据。 注&#xff1a;数据库配置比较重要 先将本地的Docker启动起来&#xff0c;用Docker管理数据库 将项目自己创建的Todo相关的都删掉…

算法笔记刷题日记——3.简单入门模拟 3.1简单模拟

刷题日记 3.1 简单模拟 此类题型根据题目描述进行代码的编写&#xff0c;考察代码能力&#xff0c;刷题记录如下&#xff1a; B1001 B1032 B1016 B1026 B1046 B1008 B1012 B1018 A1042 A1046 A1065 B1010 A1002 A1009 错题记录 B1008 数组元素循环右移问题 一个数组_A_中存有…

2.4日总结

第一题&#xff1a;选数 题解&#xff1a;思路还是很简单的&#xff0c;只需要想清楚dfs里的函数都是什么就可以了&#xff0c;还有一个简单的判断素数的函数&#xff0c;这题真没啥难度&#xff0c;就是属于基础题吧&#xff0c;请看AC代码 #include <stdio.h> #includ…

大数据分析|设计大数据分析的三个阶段

文献来源&#xff1a;Saggi M K, Jain S. A survey towards an integration of big data analytics to big insights for value-creation[J]. Information Processing & Management, 2018, 54(5): 758-790. 下载链接&#xff1a;链接&#xff1a;https://pan.baidu.com/s/1…

linux搭建jupyter

查看虚拟环境 conda info --envs进入虚拟环境 conda activate my_env pip install jupyter pip install ipykernel1. jupyter notebook启动 1.1 创建临时jupyter notebook任务 jupyter notebook --ip0.0.0.0 --no-browser --allow-root --notebook-dir/home/xxx1.2 jupyter…