TCP协议与UDP协议详解

2023-05-16

TCP协议

TCP,即Transmission Control Protocol,传输控制协议。人如其名,要对数据的传输进行一个详细的控制。

TCP协议的特点:有连接,可靠传输,面向字节流,全双工

有连接:TCP协议使用时必须先建立 TCP 连接。在传送数据完毕后,必须释放已经建立的 TCP 连接。

可靠传输:可靠传输就是数据传输过去之后,发送方知道数据发送的成功与否,如果失败会尝试再次发送

面向字节流:应用层交给TCP的报文,整个报文可能会被操作系统分组成多个的 TCP 报文,也就是一个完整的TCP报文被拆分成多个 TCP 报文进行传输

例如用TCP传输100个字节的数据:如果发送端一次发送100个字节,那么接收端可能会循环接收10次,每次接收10个字节。

全双工:TCP允许通信双方的应用进程在任何时候都能发送数据

可靠传输原理:

1、确认应答机制(可靠机制):每次发送数据之后,通过收没收到回复报文来确定发送成功与否,这样传输就变得可靠了,回复的报文称之为"应答报文",也称之为"ack报文"

接收方成功接收数据的话,会向发送方发送一个应答报文表示数据成功接收,应答报文中的标志位ACK就会被置为1(之前为0),表示数据成功接收了。并且应答报文中还会携带确认序号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。

 2、超时重传机制(可靠机制):主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B;如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发;

 但是,主机A未收到B发来的确认应答,也可能是因为ACK丢失了;因此主机B会收到很多重复数据。那么TCP协议需要用到序列号识别出那些包是重复的包,并且把重复的丢弃掉。

超时重传的时间间隔是会逐渐变大的(因为连续的超时重传是极小概率事件),如果重传一定次数之后仍然无法传输,就会尝试重置TCP连接(断开重连),如果还是连不上,此时就直接释放连接(彻底放弃)

3、连接管理机制(可靠机制):在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接

三次握手图示:

ACK和SYN都是系统内核负责的,会在收到请求之后,立即就返回

 

三次握手的意义:检查一下当前网络情况是否畅通、检查通信双方的发送能力和接收能力是否正常、协商一些重要参数

四次挥手图示:

ACK是系统内核负责的,会在收到请求之后,立即就返回,而FIN是应用程序负责的(代码中主动调用close),取决于我们的代码

 

 

4、滑动窗口(效率机制):TCP希望能够在保证可靠性的前提下,尽可能的提高传输效率,因此可以使用滑动窗口来提升效率

滑动窗口:每次批量发送一波数据,然后再等一波ACK,再发一波数据。我们把每次批量发送的数据的量称之为"窗口大小"~~

注意:接收方是收到一个数据就发送一个ACK,而不是等所有数据都到了才统一发下一组;发送方也是收到一个ACK就继续发一条数据,而不是等所有ACK都到了才统一发下一组~~

 白色窗口就表示哪些数据在等待确认,也就是在等待数据到达与接收应答报文这个过程准确无误的完成:

 

情况一:数据包已经抵达,ACK被丢了。

这种情况下,部分ACK丢了并不要紧,因为可以通过后续的ACK进行确认;

 

情况二:数据包就直接丢了。

当某一段报文段丢失之后,发送端会一直收到 1001 这样的ACK,就像是在提醒发送端 "我想要的是 1001" 一样

如果发送端主机连续三次收到了同样一个 "1001" 这样的应答,就会将对应的数据 1001 - 2000 重新发送;

这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了(因为2001 - 7000)接收端其实之前就已经收到了

这种机制被称为 "快速重传机制",它是搭配了滑动窗口机制的"超时重传"。

 

5、流量控制(可靠机制):在滑动窗口的基础之上,对发送速率做出限制的机制,也就是限制发送方的窗口大小不要太大(要合适)

接收端处理数据的速度是有限的。如果发送端发的太快,导致接收端的缓冲区被打满,这个时候如果发送端继续发送,就会造成丢包,继而引起丢包重传等等一系列连锁反应。

接收方使用接收缓冲区的剩余空间大小,来作为发送方发送速率(窗口大小)的参考数值

接收方将自己可以接收的缓冲区大小放入 TCP 首部中的 "窗口大小" 字段,通过ACK通知发送方;

接收方一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送方;发送方接受到这个窗口之后,就会减慢自己的发送速度;

如果接收方缓冲区满了,就会将窗口置为0;这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,使接收方把窗口大小告诉发送方。

 

6、拥塞控制(可靠机制):也在滑动窗口的基础之上,对发送速率做出限制的机制,也就是限制发送方的窗口大小不要太大(要合适)

TCP引入 慢启动 机制,先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据;

每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小(也就是和流量控制)做比较,取较小的值作为实际发送的窗口

 

7、延迟应答(效率机制):

延迟应答的作用就是让窗口大小在不影响接收方与发送方的处理能力的前提下尽量的大一些

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

假设接收端缓冲区为1M。一次收到了500K的数据;如果立刻应答,返回的窗口就是500K;但实际上可能处理端处理的速度很快,10ms之内就把500K数据从缓冲区消费掉了;在这种情况下,接收端处理还远没有达到自己的极限,即使窗口再放大一些,也能处理过来;如果接收端稍微等一会再应答,比如等待200ms再应答,那么这个时候返回的窗口大小就是1M;

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

那么所有的包都可以延迟应答么?肯定也不是:

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

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

 8、捎带应答(效率机制):本来ACK是系统内核负责的,会在收到请求之后,立即就返回,但是由于延迟应答机制会稍微等一会返回,这一等正好业务上也要返回内容,此时内核就可以把两个报文合二为一

 

9、面向字节流的"粘包问题":

A应用程序,需要从接收缓冲区中读取收到的数据,由于是面向字节流的,A无法确定从哪到哪是一个完整的应用层数据报

想要解决"粘包问题",只要定义应用层数据协议的时候,明确包和包之间的"边界"(比如约定使用;作为结束标记),就可以了

TCP异常情况:

1、程序崩溃:进程异常退出,操作系统会回收进程的资源,包括释放文件描述符表,这样的释放操作,就相当于调用了对应socket的close,执行close就会触发FIN报文,进一步开始四次挥手~~

2、正常关机:关机的时候,系统会强制结束所有的用户进程;之后的步骤与上述程序崩溃一样

3、主机掉电:非常突然,猝不及防的~~

掉电的是接收方:发送方是不知道对面挂了的,继续发数据(没有ack),之后触发超时重传,重传几次之后仍没有应答,尝试重置链接(也会失败,触发复位报文段RST),最后只能放弃连接

掉电的是发送方:此时接收方就等着,等一阵之后就会发送一个"心跳包",如果对方不返回"心跳包",就说明对方挂了

"心跳包"是周期性触发的,只是一个简单的不携带任何业务数据的包,存在的意义就是确认一下对方是否还在

4、网线断开:情况同主机掉电一样,只不过通信双方的主机都好着呢,这两端各自按照上述两种情况分别进行~~

TCP协议格式:

 

源/目的端口号:表示数据是从哪个进程来,到哪个进程去;

32位序号/32位确认号:32位序号针对请求数据进行的编号,32位确认序号针对应答报文(ACK报文)进行的编号。每一个ACK报文都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据;下一次你从哪里开始发。

4位TCP报头长度:表示该TCP头部有多少个32位bit(有多少个4字节);所以TCP头部最大长度是15 * 4 = 60字节

TCP报头前20个字节是固定的,后面是留给选项的,选项可有可无(它是可变的),选项可以是0个字节,最多是40个字节(什么是选项不做讨论)

6位保留位:现在虽然不用,先占个位置,以后可能会用,也就是留下的可扩展空间

6个特殊标志位(6位):

1、URG:紧急指针是否有效

2、ACK:在数据通信中,接收方发给发送方的一种传输类控制字符,表示发来的数据已确认接收无误。如果接收方成功的接收到数据,那么这一位会被置为1,也就是应答报文(ack报文)这一位置为1。

ACK是系统内核负责的,会在收到请求之后,立即就返回

3、PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走

4、RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段

5、SYN:请求建立连接;我们把携带SYN标识的称为同步报文段;SYN这一位如果为1说明这是一个同步报文段(尝试和对方建立连接)

SYN是系统内核负责的,会在收到请求之后,立即就返回

6、FIN:通知对方本端要关闭连接了,我们称携带FIN标识的为结束报文段;FIN这一位如果为1说明这是一个结束报文段(通知对方本端要关闭连接了)

FIN是应用程序负责的(代码中主动调用close),何时返回取决于我们的代码

16位窗口大小:存放当前接收方接收缓冲区的剩余大小,这个字段得是在ACK为1的时候(应答报文的时候)才有效,窗口大小是动态的(实时改变)

窗口大小最大不是64kb(也就是16位的最大值),选项中有窗口大小扩展因子来表示更大的值

16位校验和:校验和就是为了检查数据是否出错了(网络传输过程中,受到一些干扰,是容易导致传输的数据出错的),此处的检验和不光包含TCP首部,也包含TCP数据部分。

TCP校验和使用了一个比较常见的CRC算法(循环冗余校验):把TCP报文中的每个字节都进行累加,和也放到一个两个字节的数字中(加的过程中如果溢出了就溢出),最终得到的结果就是校验和

发送方发送数据的时候,就先计算一个校验和,接收方接收的时候,按照同样的规则再算一次校验和,最后看一下两次校验和是不是一样的(这里出现问题的概率还是比较小的)

16位紧急指针:标识哪部分数据是紧急数据;

UDP协议

UDP,即User Datagram Protocol,用户数据报协议

UDP协议的特点:无连接,不可靠传输,面向数据报,全双工

无连接:知道对端的IP和端口号就直接进行传输,不需要建立连接;

不可靠传输:没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会给应用层返回任何错误信息;

面向数据报:应用层交给UDP多长的报文,UDP原样发送,既不会拆分,也不会合并;

例如用UDP传输100个字节的数据:如果发送端一次发送100个字节,那么接收端也必须一次接收100个字节;而不能循环接收10次,每次接收10个字节。

全双工:UDP允许通信双方的应用进程在任何时候都能发送数据,UDP的socket既能读,也能写

UDP协议格式:

 

 源/目的端口号:表示数据是从哪个进程来,到哪个进程去;

UDP长度:16位UDP长度,表示整个数据报(UDP首部+UDP数据)的最大容量,一个UDP报文最多就只能有64KB,如果需要使用UDP传输一个比较大的数据,就需要考虑进行拆包

校验和:校验和就是为了检查数据是否出错了(网络传输过程中,受到一些干扰,是容易导致传输的数据出错的)

UDP校验和使用了一个比较常见的CRC算法(循环冗余校验):把UDP报文中的每个字节都进行累加,和也放到一个两个字节的数字中(加的过程中如果溢出了就溢出),最终得到的结果就是校验和

发送方发送数据的时候,就先计算一个校验和,接收方接收的时候,按照同样的规则再算一次校验和,最后看一下两次校验和是不是一样的(这里出现问题的概率还是比较小的)

TCP与UDP区别

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP协议与UDP协议详解 的相关文章

  • 五种知网文献免费下载方式

    1 idata中国知网 网址 xff1a idata中国知网 进入系统 xff0c 注册账号 xff0c 登录即可 每天五篇额度 xff0c 基本够用 xff0c 可注册多个账号使用 2 上海研发公共服务平台 网址 xff1a 上海研发公共
  • 【FreeRTOS】二值信号量实现线程的同步

    FreeRTOS 二值信号量实现线程的同步 测试环境如下 stm32L431RCT6 MDK keil5 stm32cube 43 FreeRTOS 一 添加多个任务 1 引脚配置 LED使用的引脚PA8和PB2设置成output 将按键引
  • 暗影精灵2pro安装win10+ubuntu16.10双系统

    暗影精灵2pro预装win10家庭版 xff0c 默认启动win10系统 xff0c 且无法引导其他系统 xff0c 今天我们来解决这个问题 先进入到win10的磁盘管理器服务 xff0c 为ubuntu单独分配磁盘空间 xff0c 让wi
  • 第二十三讲.从HadoopURL中读取数据

    视频 xff1a 美妙人生 Hadoop课程系列之HDFS 手把手教你精通HDFS 美妙人生 Hadoop课程系列之HDFS 手把手教你精通HDFS 视频笔记 从hadoop URL读取数据 static URL setURLStreamH
  • winform窗体

    一 winform介绍 WinForm xff0c 是 Net开发平台中对Windows Form的一种称谓 WinForm是窗体应用程序 xff0c 由若干个窗体应用组成 xff0c 基于C S架构 二 winform的使用 xff08
  • 赋予人工智能记忆的人,带你梳理深度学习核心算法

    新智元翻译 1 来源 xff1a Idsia 作者 xff1a J rgen Schmidhuber 翻译 xff1a 张巨岩 作者介绍 xff1a J rgen Schmidhuber 被称为是赋予人工智能记忆的人 xff0c 递归神经网
  • C++实现贪吃蛇游戏

    注意 xff1a 本代码是在VC 43 43 6 0环境下编译的 xff0c 在其他环境如codeblocks下运行可能会产生意想不到的问题 xff0c 请尽量使用VC xff01 最近由于小编闲着慌 xff0c 捣鼓了一个贪吃蛇游戏 xf
  • Win10正式版19044.2132(KB5020435)来啦!(附完整更新日志)

    微软发布了Win10正式版KB5020435 xff08 操作系统内部版本 19042 2132 19043 2132 和 19044 2132 xff09 xff0c 此次更新主要解决了某些类型的安全套接字层 xff08 SSL xff0
  • SOUI总结之皮肤说明

    皮肤说明 说明 框架自带的皮肤都是 skin sys XXXX开始 xff0c 自带的皮肤存放位置trunk soui sys resource theme sys res xff0c 图片和名称映射关系可以打开trunk soui sys
  • C++中逗号运算符

    今天测试代码的时候 xff0c 遇到一行代码出现了疑问 xff0c 原因是出现了自减运算符和逗号运算符 xff0c 这就涉及到一个顺序的问题 xff0c 于是写了一个C 43 43 小程序 xff0c 验证了一下这个想法 include u
  • PsExec的问题及其解决办法

    C gt PsExec exe 192 168 1 142 cmd PsExec v1 98 Execute processes remotely Copyright C 2001 2010 Mark Russinovich Sysinte
  • ubuntu 18.04安装protobuf

    今天需要安装protobuf 在网上搜了一篇教程 xff0c 但是篇幅太长 xff0c 于是对其进行简化一下 原文 1 96 96 96 git clone https github com protocolbuffers protobuf
  • 读取配置文件的程序

    时常会遇到需要从配置文件中读取一些信息 xff0c 这里就提供一个例子 xff0c 方便日后使用 xff1a span class token comment ini h span span class token macro proper
  • 命令行读取参数

    有时需要从命令读取一些输入 xff0c 这里找到一个方法 xff0c 怎么实现的没有仔细研究 xff0c 但是可用 cmdline h span class token comment Copyright c 2009 Hideyuki T
  • 如何在一个shell脚本中开启多个应用程序?

    之前在csdn上搜索 xff0c 提示用gnome terminal指令 xff0c 但是发现怎么都不好使 于是找到一种解决方案 span class token comment bin bash span span class token
  • 使用openCV播放视频 在视频中加入滑动条

    include 34 opencv2 highgui highgui hpp 34 include 34 opencv2 imgproc imgproc hpp 34 include lt iostream gt include lt fs
  • Linux下vscode无法查看定义?

    今天要用到vscode查到c 43 43 程序 但是发现vscode无法查看程序的定义 于是找了一下解决方法 vscode无法转到定义可能是因为没有安装插件 由于我需要使用C 43 43 所以我这里安装的是C 43 43 插件 第一步 第二
  • 冒泡排序的实现(基于顺序表)

    对于冒泡排序的含义以及图示表示 这里就不再赘述 这篇博客已经说的很明白了 添加链接描述 于是就用代码实现了一下基于顺序表的冒泡排序 因为一直看的时大话数据结构这本书 于是把上面介绍的三种实现方法都在代码中实现一下 具体实现与书中有一些出入
  • ambiguating new declaration of 问题的解决

    今天在运行代码的时候 一直在报这样的错误 ambiguating new declaration of int NewPartition seqlist int int 查看了许久 原来是头文件中的声明类型与函数实现的声明类型不一致造成的
  • opencv中的MatConstIterator,NAryMatIterator迭代器的使用

    第一个迭代器 MatConstIterator迭代器 使用迭代器计算一个三通道三维数组中 34 最长元素 34 这个代码实现过程中 照着书中的代码抄下来一直报错 后来在查阅代码的时候 发现了问题所在 具体已经在代码中标明了 include

随机推荐