そのため、生のイーサネット フレームを送受信する必要があるデバイスを使用しています。これはワイヤレス ラジオであり、イーサネットを使用してステータス メッセージをホストに送信します。使用するプロトコルは実際には 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;
}