传输层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(<…...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...

CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
Fabric V2.5 通用溯源系统——增加图片上传与下载功能
fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...