协议簇:TCP 解析: Sequence Number

简介

序列号(Sequence Number) 是 TCP 协议中非常重要的一个概念,以至于不得不专门来学习一下。这篇文章我们就来解开他的面纱.

在 TCP 的设计中,通过TCP协议发送的每个字节都对应于一个序列号. 由于每个字节都有自己的序列号,那么每个字节都可以被对方确认接收.

但是由于 TCP 使用累计确认机制,因此不需要对每个接收到的字节都发送对应的ACK,而是采用确认最后接收到的自己的序列号的方式来进行确认接收的. 举个例子,对于序列号 X, 它意味着 X 之前的所有字节已经被对方接收到(不包含 X 本身)。

序列号这个机制使得 TCP 可以检测到重复的数据包.

本篇文章中将会使用都很多我们在基本部分引入的专业术语,请参考 协议簇:TCP 解析: 基础

系列文章

协议簇:TCP 解析:基础
协议簇:TCP 解析:建立连接
协议簇:TCP 解析:连接断开
协议簇:TCP 解析:Sequence Number
协议簇:TCP 解析:数据传输

Sequence Number

正如我们所知道的,Sequence Number 字段在 TCP 头部占用 32bit 的长度。这也意味着 Sequence Number 是有限的,它的合法值是 0 - 2**32 -1. 因此对于通信双方,在发送 SEQ 时,总是需要将该值与 2 ** 32 取模.

TCP 任何一方在接收到对方发送的数据包之后,都需要对 Sequence Number 进行检查。 最通常的检查包含以下几条:

  1. 接收到的 Sequence Number 对应于那些我们已经发送还未收到 ACK 的 Sequence Number
  2. 一个TCP数据段所包含的所有字节都被当前 Sequence Number 覆盖(比如,我们可以将该段从重传队列中移除)
  3. 接收到的 Sequence Number 是我们正在等待接收的(比如,确保该 Sequence Number 于我们的接收窗口有重叠部分).
概念引入
  1. SND.UNA - 最早发送且没有收到ACK的 Sequence Number
                        [oldest unacknowledged sequence number]

  2. SND.NXT - 下一个被发送的数据的 Seuqnce Number
                        [next sequence number to be sent]

  3. SEG.ACK - 接收到的 TCP 段的 ACK,其中包含了对方期待下一个段的 Sequence Number
                        [acknowledgment from the receiving TCP (next sequence
    number expected by the receiving TCP)]

  4. SEG.SEQ - 一个 TCP 段的第一个字节的 Sequence Number
                        [first sequence number of a segment]

  5. SEG.LEN - 一个 TCP 段中包含的字节的数量
                        [the number of octets occupied by the data in the segment
    (counting SYN and FIN)]

  6. SEG.SEQ+SEG.LEN-1 - 一个 TCP 段的最后一个字节的 Sequence Number
                        [last sequence number of a segment]

  7. RCV.NXT - 下一个期待接收到的段的第一个字节的 Sequence Number. 同时,这个值也代表了接收方的接收窗口的下限.
                       [next sequence number expected on an incoming segments, and is the left or lower edge of the receive window]

  8. RCV.NXT+RCV.WND-1 - 下一个期待接收到的段的最后一个字节的 Sequence Number. 同时,这个值也代表了接收方的接收窗口的上限
                      [last sequence number expected on an incoming segment, and is the right or upper edge of the receive window]

对于数据发送方

在发送了 TCP 数据之后,正常情况下,我们都会收到相应的 ACK.

接收到的 ACK 需要满足条件: SND.UNA < SEG.ACK =< SND.NEXT

当一个处于重传队列的段的SEQ + 它的长度的和小于 ACK 的值,那么这个段已经被对方成功接收,可以从重传队列中移除。

对于数据接收方

接收到的段中包含的 SEQ 需要满足以下条件:
RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND (确保接收到的数据的第一个字节的 SEQ 处于接收窗口中)
OR
RCV.NXT =< SEG.SEQ+SEG.LEN-1 < RCV.NXT+RCV.WND (确保接收到的数据的最后一个字节的 SEQ 处于接收窗口中)

满足上述条件中任何一个条件,便可以判断当前接受到的数据部分处于接收窗口.

实际情况中,我们还需要考虑接收窗口为 0 和 空 TCP 段的情况. 那么就需要考虑以下四种情况:

Seg LenRcv WndTest
00SEG.SEQ = RCV.NXT
0>0RCV.NXT =< SEG.SEQ < RCV.NXT+RCV.WND
>00not acceptable
>0>0RCV.NXT =< SEG.SEQ < RCV.NXT + RCV.WND
OR
RCV.NXT =< SEG.SEQ+SEG.LEN-1<RCV.NXT+RCV.WND

注意,当接收窗口为 0 之后,除了ACK之外,无法接收任何其他 TCP 段. (对于上表第三条)

Initial Sequence Number Selection

TCP 协议并不限制在 TCP 的实现中重复使用同一个连接. 一个连接仅仅由一对 socket 标识. (新的连接被成为前一个连接的“化身”[incarnation]) 但是存在一个问题: 如何判断一个TCP段来自前一个连接还是前一个连接的化身? 当一个连接被快速的打开关闭或者一个连接由于内存不足而断掉,恢复后又重新建立的情况下,会尤其明显.

在上述问题中,很有可能两个连接使用相同的序列号发送数据。这种情况下,我们无法区分这个数据包的来源. 因此,对于 TCP 而言,选择一个合适的 Sequence Number 非常重要.

当我们尝试建立一个连接时,我们需要在SYN中附上我们选择的 Sequence Number,也就是 Initial Sequence Number,简称 ISN. ISN 的生成方法如下:

ISN 生成器以当前机器时钟为基础,粗略地每4微妙增加ISN的最低有效位.
这个生成器生成的序列会以 4.55 小时为周期重复,但是设计者认为没有TCP段可以在网络上存活超过这个时间,因此他们认为这样选择 ISN 是非常合理的.

对于每个TCP连接,都包含两个 Sequence Number,分别由 TCP 双方独立生成. 在一个 TCP 连接建立之前,双方应该回想通告自己的 Sequence Number (协议中称之为“synchronize”). 互相通告自己的 Sequence Number 需要每方均发送自己的 ISN 并收到对方发送的 ACK, 以确保对方收到了己方的 ISN.
大体的流程如下:
在这里插入图片描述
又由于 TCP 连接是全双工的,在接收的同时可以发送数据,那么2,3步可以合并为一步。最后, 就有了现在的 “三次握手" 了.

END!!!

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

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

相关文章

CodeTank iOS App Technical Support

CodeTank iOS App Technical Support For All Email: z253951598outlook.com TEL: 86-17782749061 App Screen Shoots

CentOS 7 防火墙命令

查看防火墙状态 systemctl status firewalld如果已经开启&#xff0c;状态为 active 如果未开启&#xff0c;状态为 inactive 开启防火墙 systemctl start firewalld关闭防火墙 systemctl stop firewalld查看当前防火墙的配置 firewall-cmd --list-all这里&#xff0c;我…

QTcpSocket connectToHost 建立连接速度慢问题

问题场景 在使用 QT 开发一个客户端 App 的时候&#xff0c;我们通过 QTcpSocket 与后台服务器进程通信。 后台程序使用其他语言编写。 问题&#xff1a; 在客户端启用之后尝试建立与后台程序的 TCP 连接的时候&#xff0c;发现连接速度非常慢&#xff08;肉眼可见的慢&#x…

GTank iOS App Technical Support

GTank iOS App Technical Support For All Email: z253951598outlook.com TEL: 86-17782749061 App Screen Shoots ​​

证书体系: CSR 解析

原文同时发布于本人个人博客&#xff1a; https//kutank.com/blog/cert-csr/ 简介 CSR 全称 “证书签名请求”(Certificate Signing Request). 本文我们将来详细的学习 CSR 的知识&#xff0c;重点集中在 CSR 所包含的信息&#xff0c;及其意义。 CSR 的作用: CSR 通常由想要获…

模拟网页行为之工具篇二

先说360浏览器&#xff0c;打开开发者选项&#xff0c;可以看到界面提供了几个功能选项&#xff0c;如图&#xff1a; 这个图片的第一个搜索图标点中过后&#xff0c;再去选中网页你感兴趣的部分就可以在Element选项中跳转到你感兴趣的代码。也可以直接ctrlF2搜寻你感兴趣网页元…

模拟网页行为之实践篇三

现在来谈下验证码图片的获取方式&#xff0c;带有验证码的地方都会附带有个刷新按钮&#xff0c;而刷新按钮的地方就是获取验证码网址代码。如果看过前面写的《模拟网页行为之工具篇》就会很容易定位到代码位置。定位到代码位置后看下图&#xff1a; 基本可以看到的是获取验证码…

SHA-256算法实现

SHA-256 算法输入报文的最大长度不超过2^64 bit&#xff0c;输入按512-bit 分组进行处理&#xff0c;产生 的输出是一个256-bit 的报文摘要。该算法处理包括以下几步&#xff1a; STEP1&#xff1a;附加填充比特。对报文进行填充使报文长度与448 模512 同余&#xff08;长度…

ecc算法入门介绍

一、从平行线谈起。 平行线&#xff0c;永不相交。没有人怀疑把&#xff1a;&#xff09;不过到了近代这个结论遭到了质疑。平行线会不会在很远很远的地方相交了&#xff1f;事实上没有人见到过。所以“平行线&#xff0c;永不相交”只是假设&#xff08;大家想想初中学习的平行…

Intel Hex概述

什么是Intel Hex文件 Intel HEX文件时遵循Intel HEX文件格式的ASCII文本文件。在Intel HEX文件的每一行都包含了 一个HEX记录。这些记录是由一些代表机器语言代码和常量的16进制数据组成的。Intel HEX文件常用来传输要存储在ROM 或者 EPROM中的程序和数据。大部分的EPROM编程器…

AndroidStudio+ideasmali动态调试smali汇编

0x00 前言 之前对于app反编译的smali汇编语言都是静态分析为主&#xff0c;加上一点ida6.6的动态调试&#xff0c;但是ida的调试smali真的像鸡肋一样&#xff0c;各种不爽&#xff0c;遇到混淆过的java代码就欲哭无泪了。后来知道IDEA用一款插件也可以实现smali的动态调试&a…

使用IDA Pro动态调试SO文件

&#xff08;1&#xff09;在IDA的安装路径中找到android_server文件。 &#xff08;2&#xff09;将android_server拷贝到手机的/data/local/tmp目录下面。 &#xff08;3&#xff09; 将手机插上电脑&#xff0c;打开命令提示符&#xff0c; 先输入”adb shell”,然后输入”…

机器学习或深度学习的数据读取工作(大数据处理)

机器学习或深度学习的数据读取工作&#xff08;大数据处理&#xff09;主要是.split和re.findall和glob.glob运用。 读取文件的路径&#xff08;为了获得文件内容&#xff09;和提取文件路径中感兴趣的东西(标签) 1&#xff0c;“glob.glob”用于读取文件路径 2&#xff0c;“.…

Android系统架构图

一、Aplications&#xff08;应用层&#xff09; 应用是用Java语言编写的云新在虚拟机上的程序。 二、Application Framework&#xff08;应用框架层&#xff09; 这一层是编写Google发布的核心应用时所使用的API框架&#xff0c;开发人员可以使用这些框架来开发自己的应用。 V…

AES算法重点详解和实现

可以看到&#xff0c;在原始数据长度为16的整数倍时&#xff0c;假如原始数据长度等于16*n&#xff0c;则使用NoPadding时加密后数据长度等于16*n&#xff0c;其它情况下加密数据长度等于16*(n1)。在不足16的整数倍的情况下&#xff0c;假如原始数据长度等于16*nm[其中m小于16]…

勒索病毒傀儡进程脱壳

样本是&#xff1a;wallet勒索病毒 环境&#xff1a;虚拟机VMWARE win7 32位 工具&#xff1a;OD&#xff0c;winhex 初次拿到样本&#xff0c;先用火绒剑工具监控下病毒样本的流程&#xff0c;可以看到有一个自创建进程的行为。 我们等找到OEP后&#xff0c;在CreateProcessA下…

arm32和arm64常用指令B BL BLX机器码计算

现在大部分手机cpu架构是ARM v7-A和ARMV8-A,&#xff0c;在ARM-v7A中常使用32位ARM指令集并且支持thumb指令集与arm的切换&#xff0c;而在ARMV8中使用的是64位ARM指令集且不再有thumb指令集状态的切换了。在调用函数时&#xff0c;会有常用的调用方式&#xff1a;BL和B&#x…

openssl c++实现bouncycastle中AES加解密

0x01 为什么要用bouncycastle 先说说JCE&#xff08;Java Cryptography Extension&#xff09;是一组包&#xff0c;它们提供用于加密、密钥生成和协商以及 Message Authentication Code&#xff08;MAC&#xff09;算法的框架和实现。 它提供对对称、不对称、块和流密码的加密…

win10用Eclipse+OpenJTag对S3C2440开发板进行动态调试

0 背景在S3C2400开发板裸板调试程序中&#xff0c;常用调试手段有三种&#xff1a;点灯法&#xff0c;串口打印&#xff0c;OpenOCD。OpenOCD又分命令行和图形界面(Eclipse)。点灯发和串口打印调试效率都很低&#xff0c;若能掌握第三种调试方法&#xff0c;会让开发过程变得高…

无源码情况下动态调试混淆的java程序

逆向工程JAVA通常是非常简单的&#xff0c;因为优秀的JAVA二进制反编译器已经存在多年。类似于jd-gui工具和恢复java二进制文件源代码功能也做的非常出色的。在这种情况下我们需要动态调试java反编译java程序的情况下&#xff0c;可以从反编译导出然后导入java IDE如Eclipse作为…