PS: 这个实现对于某些特定情况未必是最佳实现,可以用数组来代替队列来实现

参照TCP/IP详解第二卷24~29章,详细论述了TCP协议的实现,大概总结一下TCP如何向应用层保证数据包的正确性、可靠性,即TCP如何实现对数据报文的重组。

首先要设计两个报文队列,一个存放正常来到的报文,一个存放失序到来的报文。

比如正常报文队列最后一个报文数据如下:

报文数据段第一字节的序号                      数据报长度

seq1=100

len1=100

下一个来到的报文可能有多种情况,现依次分析如下:

1)正常报文

seq2=200

len2=200

seq2 = seq1+len1

由此报文的seq可知,这个报文携带数据序号200~399,正是上一个报文的预期后续报文,将此报文追加到正常报文队列。

2)完全重复报文

seq2=100

len2=100

seq2 ==seq1 而且len2==len1

这个报文携带数据序号100~199,与上一个报文携带的数据序号100~199完全一样,即完全重复,所以应该丢弃这个报文。

3)重复子报文

seq2=100

len2=50

seq2 ==seq1 而且len2<len1

这个报文携带数据序号100~149,说明这是上一个报文的一部分,所以应该丢弃这个报文。

注:第二、三这两种情况可以合并,即seq2 ==seq1 而且len2<=len1,这里分别列出只是为了说明各种不同情况。

4)部分重复报文情况一

seq2=150

len2=30

seq2>seq1而且seq2<seq1+len1而且seq2+len2<=seq1+len1

即这个报文携带序号150~179,这个序号段被包含在上一个报文段中(100~199),

所以应该丢弃这个报文。

5)部分重复报文情况二

seq2=150

len2=100

seq2>seq1而且seq2<seq1+len1而且seq2+len2>seq1+len1

即这个报文携带序号150~249,这个序号段前一部分150~199被包含在上一个报文段(100~199)中,后一部分200~249是新的数据,此时应该对这个报文作如下处理:

A.       计算重复字节数

(seq1+len1) - Seq2= 100+100-150 = 50

即这个报文段前50个字节是重复的。

B.       截取报文段新数据

丢弃这个报文段的前50字节,截取后面的新数据,即只保留字节序号段200~249。

C.       重新设置这个报文段的seq

seq2 = seq2+50 = 150+50 = 200

D.       重新设置这个报文段的数据长度

len2 = len2-50 =100-50=50

E.        重新设置后报文段如下

seq2=200

len2=50

即现在这个报文段携带数据序号200~249,正好是上一个报文的后续报文,现在可以将其作为正常报文追加到正常报文队列。

6)提前到达的报文

seq2=300

len2=100

seq2>seq1+len1

这个报文段携带序号300~399的数据,即不是上一个报文100~199的后续报文,而是提前到来的报文,此时应该将这个报文放置到失序报文队列存储起来,以备后续重组使用。

这样直到tcp断开这个socket的链接(FIN=1),此时将正常报文队列和失序报文队列中的数据合并起来,完成重组。取出正常报文队列最后一个报文 的seq和len,在失序报文队列中查找属于它的后续报文,该报文是否可以作为正常报文队列的后续报文处理过程同前面1)~5)的分析。

[转] TCP数据包重组实现分析的更多相关文章

  1. TCP协议数据包及攻击分析

    TCP/IP协议栈中一些报文的含义和作用 URG: Urget pointer is valid (紧急指针字段值有效) SYN: 表示建立连接 FIN: 表示关闭连接 ACK: 表示响应 PSH: ...

  2. Wireshark抓包工具--TCP数据包seq ack等解读

    1.Wireshark的数据包详情窗口,如果是用中括号[]括起来的,表示注释,在数据包中不占字节 2.在二进制窗口中,如“DD 3D”,表示两个字节,一个字节8位 3.TCP数据包中,seq表示这个包 ...

  3. [转]Wireshark抓包工具--TCP数据包seq ack等解读

    原文: http://blog.csdn.net/wang7dao/article/details/16805337/ ---------------------------------------- ...

  4. WireShark抓包时TCP数据包出现may be caused by ip checksum offload

    最近用WireShark抓包时发现TCP数据包有报错:IP Checksum Offload,经过查阅资料终于找到了原因 总结下来就是wireshark抓到的数据包提示Checksum错误,是因为它截 ...

  5. [置顶] NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析--吐血放送

    NS2中对TCP数据包和ACK包的TCP Sink类的主要实现代码详尽剖析,限于个人水平,如有错误请留言指出! TcpSink类的recv()方法: void TcpSink::recv(Packet ...

  6. 【转载】TCP数据包结构

    最近在研究TCP协议,找了点资料,感觉很经典,所以转载过来. 如果本文中图片不能观看,请链接原始地址:http://xinxiangsui2018.blog.163.com/blog/static/1 ...

  7. 捕获网络数据包并进行分析的开源库-WinPcap

    什么是WinPcap WinPcap是一个基于Win32平台的,用于捕获网络数据包并进行分析的开源库. 大多数网络应用程序通过被广泛使用的操作系统元件来访问网络,比如sockets.  这是一种简单的 ...

  8. tcprstat源码分析之tcp数据包分析

    tcprstat是percona用来监测mysql响应时间的.不过对于任何运行在TCP协议上的响应时间,都可以用.本文主要做源码分析,如何使用tcprstat请大家查看博文<tcprstat分析 ...

  9. 网络编程-SOCKET开发之----2. TCP粘包现象产生分析

    1. 粘包现象及产生原因 1)概念 指TCP协议中,发送方发送的若干个包数据到接收方接收时粘成一包.发送方粘包:发送方把若干个要发送的数据包封装成一个包,一次性发送,减少网络IO延迟:接收方粘包:接收 ...

随机推荐

  1. PHP框架_ThinkPHP数据库

    目录 1.ThinkPHP数据库配置 2.ThinkPHP数据库实例化模型 3.ThinkPHP数据库CURD操作 4.ThinkPHP数据库连贯操作 1.ThinkPHP数据库配置 App/Conf ...

  2. dede列表标签递增数字生成

    今天给人家调试程序,用到[field:global name=autoindex/ ] 调用指定频道.而频道前面需要加CSS代码,CSS代码正好是按序号排列的 忽然发现,是从0开始. 于是修改了一下代 ...

  3. 利用Python读取Matlab的Mat文件内容

    手头有别人写的Matlab程序,其中用到了Mat文件.现在不想安装Matlab,却又想读取Mat文件内容,该怎么办呢? 感谢scipy!!! import scipy.io data = scipy. ...

  4. cloudera目录位置

    http://www.aboutyun.com/thread-9189-1-1.html 这里来的嘿嘿. 1. 相关目录/var/log/cloudera-scm-installer : 安装日志目录 ...

  5. ubuntu删除openjdk,安装 Sun JDK

    1.到官网下载安装包: jdk-7-linux-i586.tar.gz 2.创建安装目录:sudo mkdir /usr/lib/jvm 3. 解压缩:tar zxvf ./jdk-7-linux-i ...

  6. Python4Delphi也是与VCL密切相关,所以才能相互调用,绝对有研究价值!

    Python4Delphi也是与VCL密切相关,所以才能相互调用,绝对有研究价值! http://www.cnblogs.com/GarfieldTom/archive/2013/01/17/2864 ...

  7. Arrays.sort的粗略讲解

    排序算法,基本的高级语言都有一些提供.C语言有qsort()函数,C++有sort()函数,java语言有Arrays类(不是Array).用这些排序时,都可以写自己的排序规则. Java API对A ...

  8. [置顶] export命令-linux

    export 命令 功能说明: 设置或显示环境变量. 语 法: export [-fnp][变量名称]=[变量设置值] 补充说明: 在shell中执行程序时,shell会提供一组环境变量. expor ...

  9. 【Linux】鸟哥的Linux私房菜基础学习篇整理(四)

    1. VI按键说明.(1)移动光标的方法h或向左箭头:光标向左移动一个字符:j或向下箭头:光标向下移动一个字符:k或向上箭头:光标向上移动一个字符:l或向右箭头:光标向右移动一个字符:进行多次移动,如 ...

  10. oracle中触发器中:new和:old 的使用方法--4

    转载▼     create or replace trigger TRI_PrintTest before delete or insert or update on TEST_EXAM --触发事 ...