Linux网络编程: TCP协议首部与可选项简述

一、TCP/IP五层模型

在这里插入图片描述

  1. 物理层(Physical Layer):物理层是最底层,负责传输比特流(bitstream)以及物理介质的传输方式。它定义了如何在物理媒介上传输原始的比特流,例如通过电缆、光纤或无线传输等。

  2. 数据链路层(Data Link Layer):数据链路层位于物理层之上,负责在直接相连的节点之间传输数据帧(Frame)。它将比特流组织成帧,并提供数据的可靠传输、差错检测和纠正等功能。常见的协议包括以太网(Ethernet)和Wi-Fi。

  3. 网络层(Network Layer):网络层处理分组(Packet)的传输和路由,负责将数据从源主机传输到目标主机。它定义了逻辑地址(如IP地址)和路由选择算法,并通过Internet Protocol (IP) 进行数据的分组、定址和转发。

  4. 传输层(Transport Layer):传输层提供端到端的可靠数据传输服务,负责将数据从发送方传输到接收方的端口。它通过传输协议(如TCP和UDP)提供了连接管理、流量控制、差错检测和纠正等功能。

  5. 应用层(Application Layer):应用层是最高层,负责处理特定应用程序之间的通信。它包括各种应用协议,如HTTP、FTP、SMTP和DNS等,用于实现不同应用程序之间的数据交换和通信。

二、TCP协议特点

TCP 是⾯向连接的、可靠的、基于字节流的传输层通信协议

  1. ⾯向连接:TCP是一种面向连接的协议,通信双方在传输数据之前需要先建立连接,才可以发送消息。不能像UDP协议可以⼀个主机同时向多个主机发送多播消息。

  2. 可靠性:TCP通过序号、确认和重传机制实现了数据的可靠传输,确保数据无差错、不丢失、不重复地准确到达接收方。

  3. 字节流:TCP消息是没有边界的,将数据视为一连续的字节流进行传输,所以⽆论我们消息有多⼤都可以进⾏传输。并且消息是有序的,当前⼀个消息没有收到的时候,即使它先收到了后⾯的字节,那么也不能扔给应⽤层去处理,同时对重复的报⽂会⾃动丢弃。发送方将数据划分为小的数据块,而接收方会根据需要重组这些数据块。

  4. 全双工: TCP支持全双工通信,允许双方在连接建立后同时发送和接收数据。

二、TCP协议首部

RFC

https://www.rfc-editor.org/rfc/rfc793.txt
https://www.rfc-editor.org/rfc/rfc1011.txt Urgent Pointer
https://www.rfc-editor.org/rfc/rfc1122.txt Urgent Pointer
https://www.rfc-editor.org/rfc/rfc6093.txt Urgent Pointer
https://www.rfc-editor.org/rfc/rfc2018 Selective Acknowledgment
https://datatracker.ietf.org/doc/html/rfc6691 MSS
https://www.rfc-editor.org/rfc/rfc7413.txt Fast Open

TCP协议首部

在这里插入图片描述

  • 源端口(Source Port) ,16位,指明发送数据的进程使用的端口号。
  • 目的端口(Destination Port),16位,指明数据将发往目的主机的端口号。
  • 序号(Sequence Number),32位,表示该报文段所发送数据的第一个字节的编号,在TCP连接中所传输字节流的每一个字节都会按顺序编号,由于序列号是由32位表示,所以每2^32个字节,就会产生序列号回绕,再次从0开始。在建立连接时由计算机生成的随机数作为其初始值,通过 SYN 包传给接收端主机,每发送一次数据,就「累加」一次该值。
  • 确认号(Acknowledgment Number),32位,表示接收方期望收到发送方下一个报文段的第一个字节数据的编号,也就是告诉发送方:我希望你下次发送的数据的第一个字节数据的编号为此确认号。确认号只有在ACK标志为1时才有效。发送端收到确认应答后代表确认序号之前的数据都已经被正常接收。 序号和确认号可以参考文章Linux网络编程: TCP协议之序号和确认号详解
  • 数据偏移(Data Offset),4位,他指出TCP报文段的数据起始距离TCP报文段的起始处有多远。实际上是TCP首部长度,用来标识数据段的起始位置。最大能表示的数是15,单位是4个字节,因此数据偏移的最大值是60个字节,这也是TCP首部的最大字节。因为固定首部的存在,数据偏移的值最小为20个字节,因此选项长度不能超过40字节*(减去20个字节的固定首部)。
  • 保留位(Reserved),6位,保留为今后使用,现在必须置为0。

紧接着是6位标志位。

  • URG 紧急,1位。当URG=1时,表明紧急指针字段有效。
    它告诉系统此报文段中有紧急数据,应尽快发送(相当于高优先级的数据),而不要按原来的排队顺序来传送。当URG置为1时,应用进程就告诉TCP有紧急数据要传送。于是TCP就把紧急数据插入到本报文段数据的最前面,而在紧急数据后面的数据仍然是普通数据。这时要与首部中紧急指针(Urgent Pointer)字段配合使用。
  • ACK 确认,1位。确认序号有效,只有ACK=1的时候,前面的确认号字段才有效,TCP规定,建立连接后,ACK必须为1,带ACK标志的TCP报文段称为确认报文段。
  • PSH 推送,1位。表示接收方应该尽快将这个报文交给应用层,为后续数据腾出空间。如果为1,表示对方应当立即吧数据交给上层应用,而不是缓存起来,如果应用程序不将收到的数据读走,就会一直停留在TCP接收缓冲区中。当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能收到对方的响应。在这种情况下,TCP就可以使用推送(push)操作。发送方TCP把PSH置为1,并立即创建一个报文段发送出去。接收方TCP收到PSH=1的报文段,就尽快地(即“推送”向前)交付接收应用进程。而不用再等到整个缓存都填满了后再向上交付。
  • RST 复位,1位。当RST=1时,表明TCP连接中出现了严重错误(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立传输连接。RST置为1还用来拒绝一个非法的报文段或拒绝打开一个连接。
  • SYN 同步,1位。在连接建立时用来同步序号。当SYN=1而ACK=0时,表明这是一个连接请求报文段。对方若同意建立连接,则应在响应的报文段中使SYN=1和ACK=1。因此SYN=1就表示这是一个连接请求或连接接受报文。
  • FIN 终止, 1位。断开一个连接,表示通知告知对方本段要关闭连接了,标记数据是否发送完毕,当FIN=1,表示告诉对方“我的数据已经发送完毕,你可以释放连接了”,FIN标志的TCP报文段称为结束报文段。

SYN和ACK标志用于TCP三次握手以建立连接。FIN和ACK用于TCP四次挥手断开连接。

  • 窗口大小(Window),16位。表示现在允许对方发送的数据量,也就是告诉对方,本报文段确认号开始允许对方发送的数据量,到达此值,需要ACK确认后才能继续发送数据。
    窗口指的是发送本报文段的一方的接受窗口(而不是自己的发送窗口),窗口大小是给对方用的。之所以要有这个限制,是因为接收方的数据缓存空间是有限的。
  • 校验和(Checksum),16位。检验和字段检验的范围包括首部和数据这两部分。通过CRC算法提供额外的可靠性。
  • 紧急指针(Urgent Pointer),16位。紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据)。因此,在紧急指针指出了紧急数据的末尾在报文段中的位置。当所有紧急数据都处理完时,TCP就告诉应用程序恢复到正常操作。值得注意的是,即使窗口为0时也可以发送紧急数据。但是在实际操作中很少使用紧急指针。
  • 选项部分(Options)
    长度可变,最长可达40个字节。当没有使用“选项”时,TCP的首部长度是20字节。最大长度可以根据TCP首部长度进行推算。

首部可选项

TCP头部的最后一个选项字段(options)是可变长的可选信息。这部分最多包含40字节,因为TCP头部最长是60字节(其中还包含前面讨论的20字节的固定部分)。典型的TCP头部选项结构如图所示。
在这里插入图片描述

有的TCP选项没有后面两个字段,仅包含1字节的kind字段

  • 第一个字段kind,说明选项的类型。
  • 第二个字段length,(如果有的话)指定该选项的总长度。该长度包括kind字段和length字段占据的2字节。
  • 第三个字段info,(如果有的话)是选项的具体信息

可用可选项

常见的选项有如下几种。

  1. kind=0,选项表结束(EOP)选项
    一个报文段仅用一次。放在末尾用于填充,用途是说明:首部已经没有更多的消息,应用数据在下一个32位字开始处

  2. kind=1,空操作(NOP)选项
    没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍

  3. kind=2,最大报文段长度(MSS)选项
    TCP连接初始化时,通信双方使用该选项来协商最大报文段长度。TCP模块通常将MSS设置为(MTU-40)字节(减掉的这40字节包括20字节的TCP头部和20字节的IP头部)。这样携带TCP报文段的IP数据报的长度就不会超过MTU(假设TCP头部和IP头部都不包含选项字段,并且这也是一般情况),从而避免本机发生IP分片。对以太网而言,MSS值是1460(1500-40)字节。

  4. kind=3,窗口扩大因子选项
    TCP连接初始化时,通信双方使用该选项来协商接收窗口的扩大因子。在TCP的头部中,接收窗口大小是用16位表示的,故最大为65535字节,但实际上TCP模块允许的接收窗口大小远不止这个数(为了提高TCP通信的吞吐量)。窗口扩大因子解决了这个问题。
    假设TCP头部中的接收通告窗口大小是N,窗口扩大因子(移位数)是M,那么TCP报文段的实际接收通告窗口大小是N*2M,或者说N左移M位。注意,M的取值范围是0~14。我们可以通过修改 /proc/sys/net/ipv4/tcp_window_scaling 内核变量来启用或关闭窗口扩大因子选项。
    和MSS选项一样,窗口扩大因子选项只能出现在同步报文段中,否则将被忽略。但同步报文段本身不执行窗口扩大操作,即同步报文段头部的接收窗口大小就是该TCP报文段的实际接收窗口大小。当连接建立好之后,每个数据传输方向的窗口扩大因子就固定不变了。

  5. kind=4,选择性确认(Selective Acknowledgment,SACK)选项
    TCP通信时,如果某个TCP报文段丢失,则TCP会重传最后被确认的TCP报文段后续的所有报文段,这样原先已经正确传输的TCP报文段也可能重复发送,从而降低了TCP性能。SACK技术正是为改善这种情况而产生的,它使TCP只重新发送丢失的TCP报文段,而不用发送所有未被确认的TCP报文段。选择性确认选项用在连接初始化时,表示是否支持SACK技术。我们可以通过修改 /proc/sys/net/ipv4/tcp_sack 内核变量来启用或关闭选择性确认选项。

  6. kind=5,SACK实际工作的选项
    该选项的参数告诉发送方本端已经收到并缓存的不连续的数据块,从而让发送端可以据此检查并重发丢失的数据块。每个块边沿(edge of block)参数包含一个4字节的序号。其中块左边沿表示不连续块的第一个数据的序号,而块右边沿则表示不连续块的最后一个数据的序号的下一个序号。这样一对参数(块左边沿和块右边沿)之间的数据是没有收到的。因为一个块信息占用8字节,所以TCP头部选项中实际上最多可以包含4个这样的不连续数据块(考虑选项类型和长度占用的2字节)。

  7. kind=8,时间戳选项。
    该选项提供了较为准确的计算通信双方之间的回路时间(Round Trip Time,RTT)的方法,从而为TCP流量控制提供重要信息。我们可以通过修改 /proc/sys/net/ipv4/tcp_timestamps 内核变量来启用或关闭时间戳选项。

  8. kind=34, 快速打开
    TCP Fast Open 是 Google 在 ACM CoNEXT 会议上发表的改善 Web 应用响应延时方面的一个研究成果,简单实现原理是通过修改 TCP 协议利用三次握手时进行数据交换。属于底层协议级别的优化方案,在 RTT (Round Trip Time,详见注释) 比较低时,客户端页面加载时间优化依然可以提升大约4%~5%,RTT 越长,优化效果越好,实际互联网环境下测试结果平均性能提升大约在 25%。同时因为每个请求都节省了一次RTT,在大并发情况下还可以节省处理器资源,其给出的测试数据为每秒处理事务数由 2876.4 上升到 3548.7。需要Linux内核 3.7.1 以及更高版本。

可选项抓包

抓取一个TCP连接的SYN包。
在这里插入图片描述
对齐很重要啊!

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

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

相关文章

python中字典相关知识点总结

1.字典的定义 字典:在Python中,字典是一系列键-值对。每个键都与一个值相关联,程序员可以通过键来访问与之相关联的值。 实际举例: student{name:xincun,age:18} 通过实例我们可以发现,键-值对是两个相关联的值。指…

如何实现数据库的主从复制?

如何实现数据库的主从复制? 数据库的主从复制是实现数据备份、负载均衡和故障恢复的重要策略。它涉及一个主数据库(Master)和一个或多个从数据库(Slave),主数据库负责处理写入操作,而从数据库则…

代码随想录算法训练营第二十九天|491.递增子序列、46.全排列、47.全排列 II

文档讲解&#xff1a;491.递增子序列、46.全排列、47.全排列 II 题目链接&#xff1a;491.递增子序列、46.全排列、47.全排列 II 491.递增子序列 class Solution {List<List<Integer>> res new ArrayList<>();List<Integer> path new ArrayList<…

CodeWhisperer插件

一、前言 产品官网地址&#xff1a;What is CodeWhisperer? - CodeWhisperer Amazon CodeWhisperer 是一个通用的、由机器学习驱动的代码生成器&#xff0c;可实时为您提供代码建议。在您编写代码时&#xff0c;CodeWhisperer 会根据您现有的代码和注释自动生成建议。您的个…

JAVA 100道题(6)

6.创建一个表示矩形的类&#xff0c;包括宽度和高度属性&#xff0c;以及计算面积和周长的方法。 下面是一个简单的Python类&#xff0c;表示矩形&#xff0c;包含宽度和高度属性&#xff0c;以及计算面积和周长的方法&#xff1a; python复制代码 class Rectangle: def __ini…

机器人路径规划:基于斑翠鸟优化算法(Pied Kingfisher Optimizer ,PKO)的机器人路径规划(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人&#xff08;Mobile robot&#xff0c;MR&#xff09;的路径规划是 移动机器人研究的重要分支之&#xff0c;是对其进行控制的基础。根据环境信息的已知程度不同&#xff0c;路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

【随笔馆001-安住当下是最高的人生智慧】

&#x1f332;今天我去另外一个地方参加会议&#xff0c;结束后叫了一个滴滴&#xff0c;结果司机走错了路害我等了好久。我开始有点不悦&#xff0c;突然听到马路对面有一个人在弹萨克斯。我想与其在这里焦躁地等司机&#xff0c;还不如静下心来好好欣赏音乐。就这样&#xff…

【ROS】解决编译含有Python的ROS包遇到的 “Could NOT find PY_em (missing: PY_EM)“ 问题

使用ROS编译含有Python的ROS包时会遇到 “Could NOT find PY_em (missing: PY_EM)” 的错误。这个问题通常是由于ROS找不到正确的Python解释器而导致的。解决方法&#xff1a;通过指定正确的Python解释器路径来解决这个问题。Ubuntu系统的Python解释器通常位于 /usr/bin/python…

日期问题总结

做日期问题,首先把模版写下来,再根据具体情况具体分析,基本上考试考到日期问题都是模拟和枚举,数据量也不会太大,所以我们根据题目要求直接打暴力就可以过. 模板&#xff1a; const int months[]{//平年天数 0,31,28,31,30,31,30,31,31,30,31,30,31 }; int is_leap(int y){//…

小项目知识点

0.vue运行自启动 "dev": "vite --open" //package.json 1.Element-plus 安装element-plus pnpm i element-plus 如何使用&#xff1f; <el-button :icon"Plus">按钮</el-button> <script setup langts> import { Plus …

mysql 数据库 增删改查 基本操作

目录 一 SQL 详细介绍 &#xff08;一&#xff09;SQL 分类 &#xff08;二&#xff09; SQL 语言规范 &#xff08;三&#xff09;数据库对象和命名 1&#xff0c;数据库的组件(对象)&#xff1a; 2&#xff0c;命名规则&#xff1a; &#xff08;四&#xff09; SQL…

【Rust】——panic!和不可恢复的错误

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

使用Python查找字符串中包含的多个元素

目录 一、引言 二、基本字符串操作 使用in关键字查找子字符串 使用循环和条件判断查找多个子字符串 三、使用正则表达式进行高级搜索 导入re模块 使用re.search()查找单个模式 使用re.findall()查找多个模式 四、案例与代码 五、优化与扩展 六、总结 一、引言 在Py…

【5G NB-IoT NTN】3GPP R17 NB-IoT NTN介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

20万买新能源,除了烂大街的车,还可以选“精而美”

美”文 | AUTO芯球 作者 | 雷歌 “旧车撞了&#xff0c;准备买新车”。 前几天老家一个同学发来消息&#xff0c;春节他追尾了别人的车&#xff0c;不光赔了钱&#xff0c;还把自己的车车头撞废了&#xff0c;修好得一大笔钱&#xff0c;他干脆当废铁1万块钱卖给二手车商了。…

我的自建博客之旅06之Mrdoc

这个是我折腾笔记项目的最后一篇文章了,这个项目是类似于语雀的文档笔记项目,因为我当初想找一个既可以当做笔记,又可以作为团队文档分享的笔记,除了语雀,就发现了这个项目。 这个开源项目的界面或者文档组织方式其实是我最喜欢的,但是我后来放弃它的原因是它的后台编辑逻…

React Native:跨平台移动应用开发的利器

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

nginx学习记录-目录结构及基本配置

1. nginx目录结构 执行tree命令就可以看到nginx的目录结构了&#xff0c;主要有4个&#xff0c;分别是配置目录conf&#xff0c;还有界面目录html&#xff0c;日志目录logs以及程序sbin/nginx。 2. nignx基本配置 nginx的主要配置文件为/usr/local/nginx/conf/nginx.conf&…

matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面

1、内容简介 略 65-可以交流、咨询、答疑 2、内容说明 matlab 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面 混沌系统李雅普洛夫指数谱相图分岔图和庞加莱界面 李雅普洛夫指数谱、相图、分岔图、庞加莱界面 3、仿真分析 略 4、参考论文 略

训练时损失出现负数,正常吗?为什么

在训练神经网络时&#xff0c;通常期望损失函数的值是非负的&#xff0c;因为损失函数是用来度量模型预测与真实值之间的差异的。然而&#xff0c;有时候在训练过程中&#xff0c;损失函数可能会出现负数的情况&#xff0c;这可能是正常的&#xff0c;也可能是因为某些原因导致…