C++ 使用C++;

C++ 使用C++;,c++,recv,tcpdump,C++,Recv,Tcpdump,我的网络编程经验相对有限,希望有人能帮我解答一个n00bish问题,提前感谢您的帮助!:) 我有两个C++程序单独运行。一个是使用libpcap库编写的简单数据包嗅探器,它进行过滤,以便只侦听在特定端口上接收的数据包,然后解析数据包,以便将有效负载长度和有效负载内容写入二进制文件 另一个程序是一个简单的bsd套接字服务器程序,它设置为使用recv()函数在特定端口上接收消息,然后类似地将接收到的消息长度和消息内容写入二进制文件 一切似乎都运行良好,所以当我检查二进制输出文件时,我希望内容是相同的

我的网络编程经验相对有限,希望有人能帮我解答一个n00bish问题,提前感谢您的帮助!:)

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

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

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

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

注:

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

不幸的是,由于工作场所策略,我无法上传代码。但是,我的代码的示例可以在这里找到:


再次感谢

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

TCP数据包中的数据偏移字段指示有效负载开始的点。您可以在第3.1节中了解这一点

无论如何,我建议您使用一些更高级别的库,在内部处理这些内容。使用您可以使用一些简短的代码片段来完成该任务,例如:

#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);
}
#包括
使用名称空间TIN;
布尔回调(常量PDU和PDU){
const RawPDU&raw=pdu.rfind_pdu();
//payload()返回一个std::vector
进程_有效载荷(raw.payload());
返回true;
}
int main(){
嗅探,嗅探(
“eth0”,
嗅探者:非滥交,
“某些pcap筛选器”
);
一些嗅探器。嗅探循环(回调);
}
一个是使用libpcap库编写的简单数据包嗅探器,它进行过滤,以便只侦听在特定端口上接收的数据包,然后解析数据包,以便将有效负载长度和有效负载内容写入二进制文件

TCP端口还是UDP端口

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

您如何计算有效负载长度?您应该通过获取IP数据包的总长度,从中减去IP报头长度(不是20字节,而是版本/报头长度字段中的长度,以便处理IP选项;如果该长度小于5,即小于20字节,则丢弃该数据包,这是假的),以获得TCP数据包的总长度,然后从中减去TCP头长度(不是20字节,而是“数据偏移量”字段,因此您可以处理TCP选项;如果该长度小于5,即小于20字节,则丢弃该数据包,这是伪造的)以获得TCP有效负载长度

这将处理mfontanini提到的选项以及IP选项

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

  • 如果该长度小于UDP报头中的长度,则丢弃该数据包,这是伪造的
  • 如果UDP报头中的长度小于8,则丢弃该数据包,这是伪造的
  • 否则,使用UDP报头中的长度减去8作为有效负载长度
另一个程序是一个简单的bsd套接字服务器程序,它设置为使用recv()函数在特定端口上接收消息,然后类似地将接收到的消息长度和消息内容写入二进制文件

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