libpcap数据包结果与使用C ++的bsd套接字recv数据之间的差异

时间:2013-01-30 21:27:54

标签: c++ recv tcpdump

我的网络编程经验相对有限,希望有人可以帮我解决一个非常糟糕的问题,提前感谢任何帮助! :)

我有两个单独运行的C ++程序。一个是用libpcap库编写的简单数据包嗅探器,它过滤使得它只侦听在特定端口上接收的数据包,然后解析数据包,使其将有效负载长度和有效负载内容写入二进制文件。

另一个程序是一个简单的bsd套接字服务器程序,设置为使用recv()函数接收该特定端口上的消息,然后类似地将接收到的消息长度和消息内容写入二进制文件。

一切似乎都运行良好,所以当我检查二进制输出文件时,我希望内容是相同的...但不幸的是,我发现它们只是有些相似。似乎数据包嗅探器正在捕获与服务器捕获的数据相同的数据,但它也记录了具有6字节长有效负载的额外数据包,显然服务器程序没有接收到这些数据包。

因此,数据包嗅探器正在拾取服务器不应该知道的数据包,或者服务器程序丢失它应该接收的数据包。但是,我有点确信服务器程序运行正常并且正在接收正确的消息,因此数据包嗅探器检测到的这些额外数据包让我感到困惑。有谁知道这些额外的数据包可能是什么,以及我如何过滤它们?

注意:

将数据发送到我正在侦听的端口的客户端是一个小型网络中的旧Windows NT计算机,它基本上将二进制数据传递给服务器程序进行处理。

不幸的是,由于工作场所的政策,我无法上传代码。但是,可以在此处找到我的代码的示例: http://www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html

再次感谢!

2 个答案:

答案 0 :(得分:0)

我的魔术球表明这6个字节长的有效负载可能只是TCP选项。如果您只想使用有效负载,则应跳过这些选项。请注意,某些数据包可能包含有效负载和某些选项。

TCP数据包中的数据偏移字段指示有效负载在哪个点开始。您可以在3.1节中查看here

无论如何,我建议你使用一些更高级别的库来处理内部的东西。使用libtins,您可以使用一些简短的代码段执行该任务,例如:

#include <tins/tins.h>

using namespace Tins;

bool callback(const PDU &pdu) {
    const RawPDU &raw = pdu.rfind_pdu<RawPDU>();
    // raw.payload() returns a std::vector<uint8_t>
    process_payload(raw.payload());
    return true;
}

int main() {
    Sniffer some_sniffer(
        "eth0", 
        Sniffer::NON_PROMISC,
        "some pcap filter"
    );
    some_sniffer.sniff_loop(callback);
}

答案 1 :(得分:0)

  

一个是使用libpcap库编写的简单数据包嗅探器,它过滤使得它只侦听在特定端口上接收的数据包,然后解析数据包,以便将有效负载长度和有效负载内容写入二进制文件

TCP端口或UDP端口?

如果是TCP端口,您的程序可能会收到3次握手数据包和仅ACK数据包。

您如何计算有效载荷长度?您应该通过获取IP数据包的总长度,从中减去IP标头长度(不是20个字节,而是从版本/标头长度字段的长度,以便您处理IP选项;如果该长度<5,即<&n; 20字节,只丢弃数据包,这是伪造的),以获取总TCP数据包长度,然后从中减去 TCP标头长度(不是20字节,而是“数据偏移”)字段,所以你处理TCP选项;如果那个长度是&lt; 5,即<20字节,只丢弃数据包,这是伪造的)来获得TCP有效载荷长度。

应该处理mfontanini所引用的选项,以及 IP 选项。

如果是UDP端口,您仍应处理IP选项并获取总UDP包长度,然后:

  • 如果它小于UDP标头中的长度,丢弃数据包,则是假的;
  • 如果UDP报头中的长度是&lt; 8,丢弃数据包,这是假的;
  • 否则,使用UDP标头中的长度减去8作为有效负载长度。
  

另一个程序是一个简单的bsd套接字服务器程序,设置为使用recv()函数接收该特定端口上的消息,然后类似地将接收到的消息长度和消息内容写入二进制文件。

这将不会看到初始握手或仅ACK数据包。