4

そのため、生のイーサネット フレームを送受信する必要があるデバイスを使用しています。これはワイヤレス ラジオであり、イーサネットを使用してステータス メッセージをホストに送信します。使用するプロトコルは実際には IPX ですが、IPX を実装する何十年も前のコード (TCP/IP に置き換えられたため、かなり古いもの) を掘り下げるよりも、libpcap を使用して生のイーサネット フレームを送信する方が簡単であると考えました。

私のプログラムは要求パケットを送信し (このパケットは毎回まったく同じで、ステートレスです)、デバイスは必要なデータを含む応答パケットを返します。私は pcap_inject を使用してフレームを送信し、別のスレッドで pcap_loop を使用して受信を行っています。私はもともと1つのスレッドでそれを持っていましたが、2つのスレッドを試して、私が抱えている問題を解決したかどうかを確認しました.

問題は、libpcap がリアルタイムでパケットを受信して​​いないように見えることです。それらの約5つをバッファリングしてから、一度にすべて処理するようです。それらが来るのと同じくらい速く読めるようになりたいです。libpcap でこのバッファリングを無効にする方法、またはリフレッシュ レートを上げる方法はありますか?

いくつかの出力例 (パケットが受信された時刻を出力しただけです)。各グループの間に約 1 秒の時間があることに注意してください

Time: 1365792602.805750 
Time: 1365792602.805791
Time: 1365792602.805806
Time: 1365792602.805816
Time: 1365792602.805825
Time: 1365792602.805834

Time: 1365792603.806886
Time: 1365792603.806925
Time: 1365792603.806936
Time: 1365792603.806944
Time: 1365792603.806952

Time: 1365792604.808007
Time: 1365792604.808044
Time: 1365792604.808055
Time: 1365792604.808063
Time: 1365792604.808071

Time: 1365792605.809158
Time: 1365792605.809194
Time: 1365792605.809204
Time: 1365792605.809214
Time: 1365792605.809223

挿入コードは次のとおりです。

char errbuf[PCAP_ERRBUF_SIZE];
char *dev="en0";
if(dev==NULL){
    fprintf(stderr,"Pcap error: %s\n",errbuf);
    return 2;
}

printf("Device: %s\n",dev);

pcap_t *handle;
handle=pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
if(handle==NULL){
    fprintf(stderr, "Device open error: %s\n",errbuf);
    return 2;
}

//Construct the packet that will get sent to the radio
struct ether_header header;
header.ether_type=htons(0x0170);
int i;
for(i=0;i<6;i++){
    header.ether_dhost[i]=radio_ether_address[i];
    header.ether_shost[i]=my_ether_address[i];
}

unsigned char frame[sizeof(struct ether_header)+sizeof(radio_request_packet)];
memcpy(frame, &header, sizeof(struct ether_header));
memcpy(frame+sizeof(struct ether_header), radio_request_packet, sizeof(radio_request_packet));
if(pcap_inject(handle, frame, sizeof(frame))==-1){
    pcap_perror(handle, errbuf);
    fprintf(stderr, "Couldn't send frame: %s\n",errbuf);
    return 2;
}

bpf_u_int32 mask;
bpf_u_int32 net;
if(pcap_lookupnet(dev,&net,&mask,errbuf)==-1){
    pcap_perror(handle, errbuf);
    fprintf(stderr,"Net mask error: %s\n",errbuf);
    return 2;
}

char *filter="ether src 00:30:30:01:b1:35";
struct bpf_program fp;
if(pcap_compile(handle, &fp, filter, 0, net)==-1){
    pcap_perror(handle, errbuf);
    fprintf(stderr,"Filter error: %s\n",errbuf);
    return 2;
}

if(pcap_setfilter(handle, &fp)==-1){
    pcap_perror(handle, errbuf);
    fprintf(stderr, "Install filter error: %s\n",errbuf);
    return 2;
}

printf("Starting capture\n");
pthread_t recvThread;
pthread_create(&recvThread, NULL, (void *(*)(void *))thread_helper, handle);

while(1){
    if(pcap_inject(handle, frame, sizeof(frame))==-1){
        pcap_perror(handle, errbuf);
        fprintf(stderr, "Couldn't inject frame: %s\n",errbuf);
        return 2;
    }
    usleep(200000);
}

pcap_close(handle); 
return 0;

そして受信コード:

void got_packet(u_char *args,const struct pcap_pkthdr * header,const u_char * packet){
    struct timeval tv;
    gettimeofday(&tv, NULL);
    double seconds=(double)tv.tv_sec + ((double)tv.tv_usec)/1000000.0;
    printf("Time: %.6f\n",seconds);
}


void *thread_helper(pcap_t *handle){
    pcap_loop(handle, -1, got_packet, NULL);
    return NULL;
}
4

2 に答える 2

0

pcap_set_buffer_sizeを使用してキャプチャ バッファ サイズを設定できます。キャプチャ ハンドルを有効にする前に、必ずこれを行ってください。

バッファー サイズを小さくすることは、必ずしも良い考えではありません。CPU に注意し、高いキャプチャ レートでパケットをドロップします。

于 2013-04-13T13:36:30.443 に答える