我的网络编程经验相对有限,希望有人可以帮我解决一个非常糟糕的问题,提前感谢任何帮助! :)
我有两个单独运行的C ++程序。一个是用libpcap库编写的简单数据包嗅探器,它过滤使得它只侦听在特定端口上接收的数据包,然后解析数据包,使其将有效负载长度和有效负载内容写入二进制文件。
另一个程序是一个简单的bsd套接字服务器程序,设置为使用recv()函数接收该特定端口上的消息,然后类似地将接收到的消息长度和消息内容写入二进制文件。
一切似乎都运行良好,所以当我检查二进制输出文件时,我希望内容是相同的...但不幸的是,我发现它们只是有些相似。似乎数据包嗅探器正在捕获与服务器捕获的数据相同的数据,但它也记录了具有6字节长有效负载的额外数据包,显然服务器程序没有接收到这些数据包。
因此,数据包嗅探器正在拾取服务器不应该知道的数据包,或者服务器程序丢失它应该接收的数据包。但是,我有点确信服务器程序运行正常并且正在接收正确的消息,因此数据包嗅探器检测到的这些额外数据包让我感到困惑。有谁知道这些额外的数据包可能是什么,以及我如何过滤它们?
注意:
将数据发送到我正在侦听的端口的客户端是一个小型网络中的旧Windows NT计算机,它基本上将二进制数据传递给服务器程序进行处理。
不幸的是,由于工作场所的政策,我无法上传代码。但是,可以在此处找到我的代码的示例: http://www.tcpdump.org/pcap.html http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
再次感谢!
答案 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包长度,然后:
另一个程序是一个简单的bsd套接字服务器程序,设置为使用recv()函数接收该特定端口上的消息,然后类似地将接收到的消息长度和消息内容写入二进制文件。
这将不会看到初始握手或仅ACK数据包。