用字节数组创建一个RawPacket对象

移动开发 2026-07-10

我正在开发一个Android应用,能够捕获互联网流量以便稍后分析。通过一个VPN隧道,我可以在一个 byte[] 数组中获取数据包。

是否可以仅使用一个字节数组在 PcapPlusPlus 中创建一个 pcpp::RawPacket,并使用 pcpp::PcapNgFileWriterDevice 将其保存到 file.pcap

这个示例 中,他们通过为每一层创建各自的数据来构建PCAP文件,并将它们添加到一个 pcpp::Packet,然后使用 pcpp::PcapFileWriterDevice 保存这个数据包。

但是,就我的情况而言,我只想仅用数据的字节来创建 pcpp::RawPacket。我看到有一个名为 pcpp::RawPacket::setRawData() 的方法,它接收一个指向新原始数据的指针。这个原始数据是一个字节数组吗,还是别的什么?

我尝试了以下代码:

JNIEXPORT jboolean JNICALL
Java_org_my_app_directory_pcapplusplus_PcapPlusPlusInterface_writePcapNative(
    JNIEnv *env, jclass clazz, jstring file, jbyteArray data) {

    pcpp::RawPacket rawPacket;

    // Here (I assume) should be set the whole data of the packet (and the others parameters)
    rawPacket.setRawData();

    pcpp::Packet parsedPacket(&rawPacket);

    parsedPacket.computeCalculateFields();

    // create a pcap-ng file writer. Specify file name. Link type is not necessary because
    // pcap-ng files can store multiple link types in the same file
    pcpp::PcapNgFileWriterDevice pcapNgWriter(jstring2string(env,file));

    // try to open the file for writing
    if (!pcapNgWriter.open())
    {
        std::cerr << "Cannot open output.pcap for writing" << std::endl;
        return false;
    } else {
        pcapNgWriter.writePacket(*(parsedPacket.getRawPacket()));
        pcapNgWriter.close();
    }

    return true;
}

正如你在我的函数 writePcapNative 中看到的,有一个参数 jbyteArray data,用来接收来自Java代码的 byte[],但该方法 rawPacket.setRawData() 需要一个指针(const uint8_t* pRawData)。我猜这是指向字节数组的指针,或类似的东西。

我对C++还挺新,因此不太确定是否可以获取字节数组的内存指针,并在调用方法 pcpp::RawPacket::setRawData() 时使用它,因为这个指针是一个 uint8_t

如果有其他实现方式,请告诉我。

解决方案

如果你阅读 JNI文档,第4 章的 Array Operations 部分解释了如何访问Java byte[] 数组中的原始字节(jbyteArray)。你需要的是真正的 GetByteArrayElements()ReleaseByteArrayElements() 函数,例如:

jsize rawDataLen = env->GetArrayLength(data);
jbyte* rawData = env->GetByteArrayElements(data, NULL);

// use rawData as needed, then...

env->ReleaseByteArrayElements(data, rawData, 0);

然后,在将指针传给 RawPacket 时,可以把 jbyte* 指针强制转换为 uint8_t* 指针。

另外,如果你查看 PcapPlusPlus文档,它解释说 RawPacket 类有一个内部 deleteRawDataAtDestructor 标志,默认是 true,这会导致数据包在不再需要时释放它所分配的 rawData。但在这种情况下你并不希望发生这种情况,因为数据包不会拥有Java字节数组的内存,只是引用它。因此,你需要将该标志设为 false,而我看到的唯一方法是将 rawData 指针传给数据包的构造函数,而不是传给它的 setRawData() 方法,例如:

// jbyteArray data

jsize rawDataLen = env->GetArrayLength(data);
jbyte* rawData = env->GetByteArrayElements(data, NULL);

pcpp::RawPacket rawPacket(reinterpret_cast<uint8_t*>(rawData), static_cast<int>(rawDataLen), timestamp, false);

// use rawPacket as needed, then...

env->ReleaseByteArrayElements(data, rawData, 0);
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章