TCP截包分段重组

TCP截包分段重组的设计

功能
-------
TCP报文段会有失序,重复,对于截包还会有丢包。
在进行上层协议分析之前,需要对TCP报文进行重组。
分段重组是对TCP数据进行重新排序,丢序重复的数据,并指示数据的丢失。

输入
-------
重组只处理单向数据流,所以一个TCP连接需要分别处理两个方向的数据流。
重组的数据假定已经检查了检验和。
截包重组忽略TCP窗口的大小。
简单地讲,重组仅关心TCP序号,应答号,及数据,还有几个特殊的TCP标志。
特殊的TCP标志有:SYN, ACK, RST, FIN,需要特别处理。
重组需要一个启始序号,从SYN包获取。ACK标志表示应答序号有效。
RST,FIN将设置流的结束标志,待所有数据接收完成,流才关闭。
TCP连接的关闭只能从双向流的关闭判断。

输出
-------
重组不进行上层协议的处理,因为上层协议处理需要结合双向数据流,甚至多个TCP流。
只进行缓存,对数据仅仅是压入/弹出。弹出意味着缓存数据在处理完之后进行删除。
输出为重组后的数据分段。弹出数据不必进行分段合并,可以保持原有的分段。
如果严格地实现TCP重组,应该在数据得到确认后(Acknowledged)再弹出。
但在截包数据处理中,并不是这样,只要序号连续就直接处理数据,而不进行缓存。
这是出于以下考虑:
* 等待确认就必须缓存,而多数TCP包是连续的,不需要排序,直接处理可大大提高效率。
* 数据在稍后肯定会有应答确认,只有TCP中断的情况下才有可能没有确认,这样处理影响不大。
* 对于可能的单向数据流截包分析,只能忽略确认号。
(在这种情况下,丢包会造成大量分段的缓存,需要限制分段缓存数。)


接口定义
----------
* 缓存一个TCP段。
如果这个TCP段是失序的,就要进行缓存。
大多数情况下,没有失序,就不必缓存,可以直接进行上层协议的分析。
返回布尔值指示了该数据是否进行了缓存。

* 弹出下一个TCP段。
接受一个TCP段后,或确认一个序号后,
都有可能有多个TCP段数据可以弹出进行上层协议分析。
弹出后需要删除,所以弹出操作可能是组合操作,
如判断是否有数据,取数据,删除数据,下一个数据等等。
还有可能弹出一个丢失的TCP段,即指示某段数据已丢失。

* 确认一个序号。
对未到达序号进行确认表示有数据丢失。
丢包会造成后序的TCP段都进入缓存,确认丢包可跳过丢失的序号。

* 开始,结束,重置一个序号。
对应SYN/FIN/RST标志。

* 是否已关闭。
一个TCP的关闭 = 双向数据流都已关闭。
单向数据流的关闭,除了看是否接收到FIN标志,
还要看FIN标志序号前的数据是否已全部收到,即FIN包有可能超前。

* 强制结束。在TCP结束包丢包的时候,需要强制结束一个TCP连接。
强制结束一个数据流,会造成所有缓存的数据弹出。

代码示例:

class CTcpSegments
{
public:
    void Syn(u_int32_t seq);
    void Ack(u_int32_t ack);
    void Rst(u_int32_t seq);
    void Fin(u_int32_t seq);
   
    bool Push(const u_char * data,
              unsigned int len,
              u_int32_t seq);

    // Maybe several methods:CanPop(), GetTop(), DelTop(), Next()...
    const TcpSegment_t & Pop();
       
    void ForceFin(); // ack all the buffered and set fin
    bool IsClosed() const;
}   

使用示例
-----------
假设有一个CTcpConnection对象,处理一个IP:Port地址对上的TCP流。
CTcpConnection有两个CTcpSegments对象,分别重组客户端和服务端的TCP数据流。

class CTcpConnection
{
    ...
    CTcpSegments m_clt, m_svr;
}

例如对于一个客户端发往服务端的TCP包数据,则如下处理:

1. 处理被应答的服务端数据
m_svr.Acknowledge(nAck);
while (m_svr.CanPop())
    DealSvrData(m_svr.Pop());

2. 处理当前TCP包的数据
m_clt.Push(...);
while (m_clt.CanPop())
    DealCltData(m_clt.Pop());

3. 处理FIN/RST标志
if (TCP_FIN & cTcpFlags)
    m_clt.Fin(nSeq);
if (TCP_RST & cTcpFlags)
    m_clt.Rst(nSeq);

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
由于TCP分段重组过程比较复杂,需要用到网络协议栈和操作系统的相关接口,因此本人作为AI语言模型无法直接提供完整的代码。以下是一个示例TCP分段重组的流程,供参考: 1. 建立TCP连接 在客户端和服务器之间建立TCP连接,双方协商好通信参数,括端口号、初始序列号、窗口大小等。 2. TCP分段 当发送方需要发送大量数据时,会将数据分为若干个TCP数据段进行传输。每个TCP数据段都TCP头部和数据部分。TCP头部含了序列号、确认号、窗口大小等信息,用于控制数据传输的流程。 3. IP分片 由于网络传输的限制,较大的IP数据需要分成若干个较小的IP分片进行传输。每个IP分片都含IP头部和数据部分。IP头部含了源地址、目的地址、协议类型等信息,用于在网络中正确路由。 4. 数据传输 TCP数据段被分成若干个IP分片后,逐一在网络中传输。每个IP分片都需要经过网络层和链路层的处理,括添加和删除各自的头部和尾部信息。 5. IP重组 当接收方接收到多个IP分片时,需要根据IP头部中的标识符和偏移量信息,将分片按照正确的顺序重组成完整的IP数据。由于IP分片的大小不一定相同,重组过程中需要进行缓存和拼接操作。 6. TCP重组 TCP数据段被分成若干个IP分片后,逐一在网络中传输。当接收方接收到多个TCP数据段时,需要根据TCP头部中的序列号和确认号信息,将数据段按照正确的顺序重组成完整的TCP数据流。由于TCP数据段的大小不一定相同,重组过程中需要进行缓存和拼接操作。 7. 关闭TCP连接 当通信结束时,需要通过TCP的四次挥手过程关闭TCP连接,双方释放资源并结束通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值