在发送数据包之前读取TCP序列号

M.S*_*sti 1 c sockets linux tcp

我正在Linux下编写一个C/C++客户端 - 服务器程序.假设将消息m从客户端发送到服务器.

在发送m之前,客户端是否可以读取将携带m的数据包的TCP序列号?

实际上,我想将此序列号附加到m,并发送生成的数据包.(嗯,事情变得更复杂,但让我们保持这么简单.事实上,我想将身份验证信息应用于此序列号,然后将其附加到m.)

此外,

是否有可能服务器读取携带m的数据包的TCP序列号?

Omn*_*ous 6

你可以做一些非常接近于此的事情.您可以计算发送的所有字节数,并在消息结束时将消息之前发送的所有字节数计算在内.

任何人在谈论TCP的'数据包'时,我都会感到非常紧张.因为如果你在谈论数据包和TCP的同时混合不应混合的协议级别.您在TCP中发送的数据与通过IP发送的数据包之间没有任何有意义的对应关系.

是的,IP数据包中有序列号用于发送TCP信息.这些序列号是到目前为止发送的字节数(也称为八位字节)的计数.它们识别数据包中字节所属的流在哪里,但它们与数据包无关.

如果发生重发,或者您正在使用Nagle算法,或者当天的TCP堆栈感觉如此,您可能最终会在同一个数据包中结束两次发送操作.或者,最终可能会有一半的发送操作以一个数据包结束,另一半则在另一个数据包中.每个数据包都有自己的序列号.

正如我所说,在传输层执行的发送操作与在网络层发送的数据包之间绝对没有任何有意义的关系.我理论上也不是在谈论.它并不是"真正的所有数据包下面和发送一般,除非一些奇怪的条件,将所有字节放在一个数据包中".不,我在上面概述的场景,其中来自单个发送操作的字节被扩展到多个分组经常发生并且在不可预测的条件下发生.

所以,我不知道为什么你想知道数据包中的序列号.但是如果您使用序列号作为发送字节数的代理,您可以自己保留该数量,并将其自己填入流中.并记得计算这些字节.


J-1*_*DiZ 5

不,你不能那样做——至少没有预期的结果

这是因为:

  • TCP 是基于流的,而不是基于数据包的。
  • TCP 序列号以字节为单位,而不是数据包。
  • 底层 TCP 层为您做分段。
  • TCP 窗口大小/数据包大小是动态的

这意味着您可能会在“数据包”的末尾发送一个带有序列号的“数据包”。事实证明,底层的魔法会重新分割你的数据包。

你想要什么:

    1   2   3   4
  +---+---+---+---+          
  | A | B | C |"1"|  packet 1, seq=1, len=4
  +---+---+---+---+          

    5   6   7   8
  +---+---+---+---+          
  | A | B | C |"5"|  packet 2, seq=5, len=4
  +---+---+---+---+          
Run Code Online (Sandbox Code Playgroud)

你可能会得到什么:

    1   2   3   4         
  +---+---+---+---+ 
  | A | B | C |"1"|    packet 1 (seq=1, len=4)
  +---+---+---+---+ 

 (packet 1 got lost) 

    1   2   3   4   5   6
  +---+---+---+---+---+---+
  | A | B | C |"1"| A | B |   packet 1, resent, seq=1, len=6
  +---+---+---+---+---+---+ 

    7   8
  +---+---+
  | C |"5"|  packet 2, seq=7, len=2
  +---+---+
Run Code Online (Sandbox Code Playgroud)