传输层TCP协议
一、TCP协议格式

我们看到报头固定有20字节,最后选项大小不固定。
4位首部长度(二进制0000 ~ 1111,十进制范围[0, 15])单位是4字节(存放字节大小范围[0, 60])包括了20字节固定长度 +选项长度。若选项大小为0,四位首部长度是5,即0101,用于解包。
二、TCP各种机制
1、确认应答机制
保证双方请求发送可靠性。

发送方和接收方不一定就是 client 和 server ,身份可以互换,上图举例。
只要 client 收到应答,就能保证上次 client 发送的请求 server 一定接收到了,这是保证了从 client 到 server 的数据发送可靠性。但是我们不能对应答再次应答来保证从 server 到 client 数据发送的可靠性,因为这样会死循环,所以一般不对应答进行处理。
可靠性:不是TCP协议保证每一个请求都能让发送方收到应答,而是能确认接收方是否得到了请求,如果得到发送方收到应答,没有就是发送方没收到应答。
TCP通信模式
首先由于应用层会有发送缓冲区和接收缓冲区来进行通信,Linux中把缓冲区以字节为单位逻辑上看成是数组,数字就是数组的下标,序号与确认序号就是这样的缓冲区中的数组下标。


2、超时重传机制
由确认应答机制可以知道,我收到了 ACK 就说明对方一定收到了数据,经过一段时间我没有收到 ACK,TCP协议规定我认为对方没有收到数据,我要补发数据。
没有收到 ACK 两种情况:

那么经过多长时间进行数据补发呢?与网络相关,Linux 中第一次超时0.5s,第二次超时1s,第三次超时2s,第一次超时4s...重复一定次数还没有收到就关闭不传了。
3、连接管理机制
正常情况下,三次握手建立连接,四次挥手断开连接。
(1)三次握手建立连接
标记位 SYN 表示申请建立连接
标记为 RST 表示要再次建立连接

我们看到最后一次服务器没有对 ACK 进行应答,实际上就算连接在最后一步出现问题,导致没有连接成功,客户端在发起 ACK 之后就认为连接已经建立,此时对服务器发送请求时,服务器发现没有连接成功就会返回 RST,客户端看到后就知道没有建立连接,重新三次握手建立连接。
(2)四次挥手断开连接

第一次挥手表示客户端向服务器发送的数据已经发完,之后客户端不会主动发消息给服务器,但由于没有第二次挥手,服务器还可以继续给客户端发消息,客户端也必须 ACK 应答,但应用层已经关闭,只能发 ACK 应答报头。
所以允许客户端还要收到服务器的消息就只能关闭套接字的写端。
用函数 int shutdown(int sockfd, int how) how中的选项 SHUT_WR 关闭写端。
(3)建立连接为什么要三次握手?
网络中有许多连接,为了管理连接就要先描述再组织,连接就是一个结构体,既要有空间存储,也要有时间来进行属性更新。所以三次握手也是在维护双方的连接结构体。
而且三次握手要有三次才能建立连接,对抗 SYN 洪水效果好。
原因:
a、验证全双工:即保证双方网络连通性,用最小的次数验证。
b、建立双方通信共识:客户端发送 SYN 说明客户端想连接服务器,服务器也发 SYN 说明服务器想连接客户端。
c、协商双方接受能力,在 ACK 应答报头中会带有16位窗口大小,这就是说当前接受缓冲区剩余量,用于为下一次数据发送进行发送量的确定。
(4)四次挥手中状态含义
服务器 CLOSE_WAIT 状态:客户端已经退出,服务器知晓,但是还不能立即关闭自己的 connfd
客户端 TIME_WAIT 状态:TCP规定,处于 TIME_WAIT 状态下在 2 * MSL(maximum segment lifetime 报文最大生存时间) 时间内不能再次监听同一个端口。
主动断开连接的一方最终会进入 TIME_WAIT 状态。
那如何不用等就可以重新监听端口呢?
int setsockopt(int sockfd, int level, int optname, void* optval, socklen_t* optlen)
level:所在层,SOL_SOCKET
optname:选项名字,SO_REUSEADDR,重新使用地址
optval:选项值,int opt = 1
optlen:选项大小,sizeof opt
函数作用是允许创建端口号相同,但IP地址不同的 socket 描述符,不用等就可以连接相同端口。
为什么要等 2MSL 时间,要有 TIME_WAIT ?
a、保证两个朝向尚未接受或迟到的报文在 2MSL 时间内被接受后丢弃(因为已经是超时报文)如果没有 TIME_WAIT,立即建立相同的连接,就会接收到之前的旧数据,导致数据错误。
b、同时也保证四次挥手最后的 ACK 服务器能就收到,要是没有 TIME_WAIT,客户端立即退出,ACK 传递出错,服务器再次向客户端发送 FIN 时客户端退出就会导致错误。
(5)连接管理总流程

4、流量控制
发送方会根据接收方的接收缓冲区剩余空间来动态调整发送速度。
所以接收方可以在 ACK 应答中的16窗口大小填写缓冲区剩余量来告知发送方。

窗口探测:主机A给主机B发空报头,B必须 ACK 应答带上窗口大小,主机A就能了解情况。
窗口更新通知:主机B终于能有空间接收请求时,会给主机A发消息,提醒他可以发数据了。
标记位 URG:紧急指针标记位(0无效,1有效)数据中有紧急数据,16位紧急指针就会标识紧急数据在数据中的偏移量。因为TCP协议中紧急数据大小1字节,所以只有偏移量没有大小。举例:0代表正常,1代表暂停,2代表取消...读取紧急数据知晓方法对应上层对于数据的处理方法。
recv 和 send 函数里面的 flag 标记设成 MSG_OOB 就可以对紧急数据设置。
5、滑动窗口
问题
流量控制:具体怎么控制发送数据大小?
超时重传:超时时间内,已发送的数据不能丢弃,保存在哪里?
发送方规定了一个滑动窗口,在窗口内的数据可以直接发送,暂时不用收到应答。

根据感性的理解,滑动窗口是可以变大变小变成0,只能向右移。
构建模型:
缓冲区在Linux里面逻辑上看成是字节为单位的数组,则滑动窗口就是用双指针(win_start , win_end)维护的内存空间。
接收到 ACK 应答之后,win_start = 确认序号,win_end = win_start + 16位窗口大小。
考虑一个问题:如果数据丢包,滑动窗口如何移动?
建立模型

1、最左侧报文丢失
即2000的报文丢失,此时传来的 ACK 确认序号只能是1001,由于我们一次发送多条数据,应答回来的都是1001,超过3次重复应答,发送方就会意识到1001~2000的报文已经丢失,再次补发,下一次 ACK 确认序号就直接是5001,这就是快重传机制。

上述情况是报文丢了,但如果应答丢了呢?没关系,只要相信最新一次应答的确认序号就能确定下一次报文从哪里开始发送(由确认序号定义得知)
所以最左侧报文丢失移动策略:
a、由于确认序号规定的约束,滑动窗口左边界不动。
b、快重传和超时重传对左侧报文补发。
快重传 vs 超时重传
快重传要连续3次相同确认序号才能触发(保证效率),但是在极端情况下超时重传一定能识别到报文丢失(保证安全)
2、中间报文丢失
a、win_start = 确认序号,此时新滑动窗口就是最左侧报文丢失
b、由于确认序号规定的约束,滑动窗口左边界不动。
c、快重传和超时重传对左侧报文补发。
3、最右侧报文丢失
a、win_start = 确认序号,此时新滑动窗口就是最左侧报文丢失
b、由于确认序号规定的约束,滑动窗口左边界不动。
c、快重传和超时重传对左侧报文补发。
所以最后我们来回答最开始的两个问题。
流量控制:具体怎么控制发送数据大小?滑动窗口机制
超时重传:超时时间内,已发送的数据不能丢弃,保存在哪里?滑动窗口里面,出问题转化成最左侧报文丢失问题即可解决。
6、拥塞控制
(1)介绍网络拥塞
由于网络拥堵导致发送报文大面积的丢包,TCP会采用慢启动机制,先发少量的数据, 探探路, 摸清当前的网络拥堵状态, 再决定按照多大的速度传输数据。
TCP解决网络拥塞的问题,最大的价值在于:在多个使用同一网络进行通信的主机有拥塞避免的共识。即TCP协议是全体主机都要遵守的,在网络拥塞的情况下,不能只从一台主机考虑,全体主机都必须减少报文发送才能缓解网络拥塞。
具体的拥塞控制:发送方的滑动窗口 = min(接收方的应答窗口,拥塞窗口)
(2)拥塞窗口
网络状况是浮动的,就说明拥塞窗口的大小肯定也是动态变化的。所以要经过多轮尝试才能得出准确的拥塞窗口大小。
慢启动机制

但是如果只是单纯向上面一样指数级增长就会导致测出来的拥塞窗口不准确,所以慢启动之后我们要让拥塞窗口线性增长来保证准确。

加法增大:达到阈值之后只能线性增长来探测到准确的网络拥塞值。
乘法减少:上一次的网络拥塞值的一半就是下一次慢启动的阈值。
但是不会无限线性增大下去,一定会有拥塞窗口极限值限制线性增长。
7、延迟应答
收到一批报文之后不会立即应答,等上层处理完一些请求之后能空出更多的接收窗口了,再 ACK 应答告知对方有更大的接收窗口,可以在网络不拥堵时保证传输效率。
但是延迟应答也有限制。
8、捎带应答
发送数据时带上上一次的应答数据
三、理解TCP面向字节流
四、TCP粘包问题
1、介绍粘包问题
2、解决粘包问题
3、UDP不用考虑粘包问题
五、TCP异常
六、TCP小结
可靠性: 校验和,序列号(按序到达) ,确认应答机制,超时重传机制,连接管理机制,流量控制机制,拥塞控制机制
七、TCP / UDP对比
八、用UDP实现可靠性传输
1、引入超时重传机制,防止丢包
2、引入确认应答机制,保证对方收到数据
3、引入序号,保证数据接收顺序
相关文章:
传输层TCP协议
一、TCP协议格式 我们看到报头固定有20字节,最后选项大小不固定。 4位首部长度(二进制0000 ~ 1111,十进制范围[0, 15])单位是4字节(存放字节大小范围[0, 60])包括了20字节固定长度 选项长度。若选项大小为…...
自己开发一个网站系列之-网页开发初识
自己开发一个网站系列之-网页开发初识 欢迎来到网页开发的世界!在这个教程中,我们将介绍网页开发的基本概念、工具和技术,让你能够从零开始创建自己的网页。 一、基础概念 1. 什么是网页? 网页是通过互联网进行访问的文档&#…...
【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法
目录 一、Floyd算法与A * 算法 1、Floyd算法 思想 伪代码 2、 A * 算法 思想 伪代码 二、经典题目 题目一:卡码网 97. 小明逛公园 题目链接 题解:Floyd 算法 题目二:卡码网 127. 骑士的攻击 题目链接 题解:A * 算法&a…...
docker和ufw冲突问题
在ubuntu上部署的docker映射的端口,开启防火墙ufw后,在未放通的状态下,还是可以访问 解决办法: 在/etc/docker/daemon.json添加如下配置 {"iptables": false } 然后重启docker服务即可 systemctl daemon-reload s…...
Java(基本数据类型)( ̄︶ ̄)↗
Java 基本数据类型是Java编程语言中用于存储数据值的基本单位。它们直接映射到硬件的处理器上,因此访问速度非常快。Java中的基本数据类型分为四大类:整型、浮点型、字符型、布尔型。每种类型都有其固定的范围和存储大小。 一、整型 1)byte…...
283. 移动0
class Solution(object):def moveZeroes(self, nums):""":type nums: List[int]:rtype: None Do not return anything, modify nums in-place instead."""# 两个指针,left, right,中间夹的都是0,# 像个虫子一样一纵一纵的…...
Mysql删库跑路,如何恢复数据?
问题 删库跑路,数据还能恢复吗? 我们经常听说某某被领导训斥了,对领导心生痛恨,然后登录 Mysql 删库跑路。对于闲聊中经常听说过的一个段子,在现实生活中是否真的发生过,如果发生了,我们该如何解…...
【HarmonyOS】应用引用media中的字符串资源如何拼接字符串
【HarmonyOS】应用引用media中的字符串资源如何拼接字符串 一、问题背景: 鸿蒙应用中使用字符串资源加载,一般文本放置在resoutces-base-element-string.json字符串配置文件中。便于国际化的处理。当然小项目一般直接引用字符串,不需要加载s…...
打开ffmpeg编码器的时候报错:avcodec_open2()返回-22
[h264_v4l2m2m 0x555555617a00] Could not find a valid device [h264_v4l2m2m 0x555555617a00] cant configure encoder 前言:先做一个操作,查找编码器的时候,使用名字查找的方式: const AVCodec *avcodec_find_encoder_by_n…...
R包:ggheatmap热图
加载R包 # devtools::install_github("XiaoLuo-boy/ggheatmap")library(ggheatmap) library(tidyr)数据 set.seed(123) df <- matrix(runif(225,0,10),ncol 15) colnames(df) <- paste("sample",1:15,sep "") rownames(df) <- sapp…...
springboot实战学习(7)(JWT令牌的组成、JWT令牌的使用与验证)
接着上篇博客的学习。上篇博客是在基本完成用户模块的注册接口的开发以及注册时的参数合法性校验的基础上,基本完成用户模块的登录接口的主逻辑以及提到了问题:"用户未登录,需要通过登录,获取到令牌进行登录认证,…...
如何使用numpy反转数组
如何使用numpy反转数组 1、使用np.flip()函数 可以使用flip(m, axisNone)函数来对数组进行反转: m:输入数组 axis:为None则行列都反转 axis:为0则反转行 axis:为1则反转列2、代码 import numpy as np# 创建一维数组 arr np.array([[1, 2, 3, 4, 5],[2, 2, 3, 4…...
Linux·进程概念(上)
1.操作系统 任何计算机系统都包含一个基本的程序合集,称为操作系统(Operator System)。笼统的理解,操作系统包括: 内核(进程管理,内存管理,文件管理,驱动管理) 其他程序(函数库,shell程序) OS的…...
Javax Validation 自定义注解校验(身份证号校验)
一、场景分析 我们使用 SpringMVC 在 Controller 层,对身份证号进行数据校验的话,经常采用以下方式: RestController RequiredArgsConstructor RequestMapping("member") public class MemberController {// 身份证号码正则表达式…...
nid修改orac库和实例名为jyc
由于库太大,并且要求修改源库的实例名,所以考虑采用nid方式重建控制文件,实现名称和路径的完美替换。 oracleJYCDB:/home/oracle/scripts> oracleJYCDB:/home/oracle/scripts>echo $ORACLE_SID orac oracleJYCDB:/home/oracle/scripts…...
无人机之模拟图传篇
无人机的模拟图传技术是一种通过模拟信号传输图像数据的方式,它通常使用无线电模块或专用通信协议进行数据传输。 一、基本原理 模拟图传技术的工作原理是将摄像头或相机设备采集到的图像数据,通过模拟信号的形式进行传输。这些模拟信号在传输过程中可能…...
Ubuntu 20.04安装pycharm2022及配置快捷方式
一、下载与安装 1. 下载 在 官网 下载所需版本,如:下载 2022.3.3 - Linux (tar.gz) 2. 安装 设置自定义安装路径(推荐在 /opt/ 路径下)并安装 mkdir -p ~/Documents/software/pycharm/ cd ~/Documents/software/pycharm/ mv ~/Downloads/pycharm-c…...
uni-app - - - - - 实现锚点定位和滚动监听功能(滚动监听功能暂未添加,待后续更新)
实现锚点定位和滚动监听功能 1. 思路解析2. 代码示例 效果截图示例: 点击左侧menu,右侧列表数据实现锚点定位 1. 思路解析 点击左侧按钮,更新右侧scroll-view对应的scroll-into-view的值,即可实现右侧锚点定位滚动右侧区域&am…...
wordpress迁移到别的服务器
wordpress论坛网站搭建 于2023/11/16写的该文章 一-配置环境 配置LNMP(linuxnginxmysqlphpphpmyadmin)环境或者LAMP(apache) 可以选择集成了这些软件的套件 下载链接:https://www.xp.cn/download.html 手动下载这…...
cefsharp新版本OnBeforeResourceLoad 禁止http自动跳转https显示404错误解决办法 含代码
一、问题 因项目需要,域名没有ssl证书,结果http访问时被强制定向到https前缀,结果会显示404 测试版本cefsharp126.x (x64) 框架 CefSharp.WinForms.NETCore 二、代码(核心代码) 如果请求url是http,且目标是https时,则阻止请求 //判断请求变化 if (url.StartsWith(<…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
