如何使用 winpcap 分配内存以高性能发送大型 pcap 文件(大小大于可用内存)?

发布于 2024-12-12 12:48:45 字数 2624 浏览 0 评论 0原文

我已使用 winpcap 示例中的代码发送 pcap 文件(来自 winpcap 文档的原始代码位于 此链接

发送小 pcap 文件效果很好,但如果我尝试发送大 pcap 文件(大于可用内存大小,例如 2 Gb),它会肯定会失败。此代码用于在内存中分配文件的大小,以便稍后发送。

caplen= ftell(capfile)- sizeof(struct pcap_file_header);
...
/* Allocate a send queue */
squeue = pcap_sendqueue_alloc(caplen);

问题是如何使其适用于大文件(以 GB 为单位或大于可分配的最大内存空间)?例如,我是否应该只分配 100 Mb 并发送队列,然后获取下一个 100 Mb?如果是的话,适当的缓冲区大小是多少?以及如何做到这一点?

这里的一个重要问题是发送该文件的性能,需要尽快完成(我正在发送视频数据包)。

总之这里如何管理内存来达到这个目的呢?

有人有适当的解决方案或建议吗?


示例代码片段(此问题的不必要代码被替换为...)

...
#include <pcap.h>
#include <remote-ext.h>

...

void main(int argc, char **argv)
{
pcap_t *indesc,*outdesc;
...
FILE *capfile;
int caplen, sync;
...
pcap_send_queue *squeue;
struct pcap_pkthdr *pktheader;
u_char *pktdata;
...

/* Retrieve the length of the capture file */
capfile=fopen(argv[1],"rb");
if(!capfile){
    printf("Capture file not found!\n");
    return;
}

fseek(capfile , 0, SEEK_END);
caplen= ftell(capfile)- sizeof(struct pcap_file_header);
fclose(capfile);

...

...

/* Open the capture file */
if ( (indesc= pcap_open(source, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
{
    fprintf(stderr,"\nUnable to open the file %s.\n", source);
    return;
}

/* Open the output adapter */
if ( (outdesc= pcap_open(argv[2], 100, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
{
    fprintf(stderr,"\nUnable to open adapter %s.\n", source);
    return;
}

...

/* Allocate a send queue */
squeue = pcap_sendqueue_alloc(caplen);

/* Fill the queue with the packets from the file */
while ((res = pcap_next_ex( indesc, &pktheader, &pktdata)) == 1)
{
    if (pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
    {
        printf("Warning: packet buffer too small, not all the packets will be sent.\n");
        break;
    }

    npacks++;
}

if (res == -1)
{
    printf("Corrupted input file.\n");
    pcap_sendqueue_destroy(squeue);
    return;
}

/* Transmit the queue */



if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len)
{
    printf("An error occurred sending the packets: %s. Only %d bytes were sent\n", pcap_geterr(outdesc), res);
}


/* free the send queue */
pcap_sendqueue_destroy(squeue);

/* Close the input file */
pcap_close(indesc);

/* 
 * lose the output adapter 
 * IMPORTANT: remember to close the adapter, otherwise there will be no guarantee that all the 
 * packets will be sent!
 */
pcap_close(outdesc);


return;
}

I have used the code from winpcap example to send pcap file(original code from winpcap documenation found at this link)

It works fine to send a small pcap files but if I tried to send a large pcap file (larger than available memory size say 2 Gb) it will fail for sure. This code is used to allocate size of the file in memory in order to send it later

caplen= ftell(capfile)- sizeof(struct pcap_file_header);
...
/* Allocate a send queue */
squeue = pcap_sendqueue_alloc(caplen);

The question is how to make this work for large files(in Gb or larger than maximum memory space available for allocation)? Should I allocate only 100 Mb for example and send the queue and then take the next 100Mb? If yes what is the proper buffer size? And how to do this?

an important issue here is the performance of sending this file which needed to be done as fast as can (i am sending a video packets).

In short how to manage the memory here to achieve this goal?

Would anyone have a proper solution or suggestion?


Snippet from example code (unnecessary code for this question replaced by ... )

...
#include <pcap.h>
#include <remote-ext.h>

...

void main(int argc, char **argv)
{
pcap_t *indesc,*outdesc;
...
FILE *capfile;
int caplen, sync;
...
pcap_send_queue *squeue;
struct pcap_pkthdr *pktheader;
u_char *pktdata;
...

/* Retrieve the length of the capture file */
capfile=fopen(argv[1],"rb");
if(!capfile){
    printf("Capture file not found!\n");
    return;
}

fseek(capfile , 0, SEEK_END);
caplen= ftell(capfile)- sizeof(struct pcap_file_header);
fclose(capfile);

...

...

/* Open the capture file */
if ( (indesc= pcap_open(source, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
{
    fprintf(stderr,"\nUnable to open the file %s.\n", source);
    return;
}

/* Open the output adapter */
if ( (outdesc= pcap_open(argv[2], 100, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf) ) == NULL)
{
    fprintf(stderr,"\nUnable to open adapter %s.\n", source);
    return;
}

...

/* Allocate a send queue */
squeue = pcap_sendqueue_alloc(caplen);

/* Fill the queue with the packets from the file */
while ((res = pcap_next_ex( indesc, &pktheader, &pktdata)) == 1)
{
    if (pcap_sendqueue_queue(squeue, pktheader, pktdata) == -1)
    {
        printf("Warning: packet buffer too small, not all the packets will be sent.\n");
        break;
    }

    npacks++;
}

if (res == -1)
{
    printf("Corrupted input file.\n");
    pcap_sendqueue_destroy(squeue);
    return;
}

/* Transmit the queue */



if ((res = pcap_sendqueue_transmit(outdesc, squeue, sync)) < squeue->len)
{
    printf("An error occurred sending the packets: %s. Only %d bytes were sent\n", pcap_geterr(outdesc), res);
}


/* free the send queue */
pcap_sendqueue_destroy(squeue);

/* Close the input file */
pcap_close(indesc);

/* 
 * lose the output adapter 
 * IMPORTANT: remember to close the adapter, otherwise there will be no guarantee that all the 
 * packets will be sent!
 */
pcap_close(outdesc);


return;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

强者自强 2024-12-19 12:48:45

只需将其上限设置为 50 MB(这有点随意,但我认为合理的起点),并增强代码位,当并非所有数据包都适合队列时发出警告,以便它只发送到目前为止所拥有的数据并启动用剩余的数据包从头开始填充队列。

Just cap it at say 50 MB (this is a somewhat arbitrary but I think reasonable starting point), and enhance the bit of code that warns when not all the packets fit in the queue so that it just sends what it has so far and starts filling the queue from the beginning with the remaining packets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文