1.網絡編程在自己定義結構體實現協議的時候,一定要注意字節對齊這個問題。否則sizeof和強制轉換指針的時候都會出現很難發現的bug。
什麼是字節對齊自行百度。
1 #pragma pack (1)//字節對齊的控制!非常注意! 2 //定義一個以太網頭部 3 typedef struct ehhdr 4 5 { 6 7 UCHAR eh_dst[6]; /* destination ethernet addrress */ 8 9 UCHAR eh_src[6]; /* source ethernet addresss */ 10 11 USHORT eh_type; /* ethernet pachet type */ 12 13 }ETHERHEAD; 14 15 //28字節的ARP請求/應答 16 17 typedef struct arphdr 18 19 { 20 21 USHORT arp_hrd; /* format of hardware address */ 22 23 USHORT arp_pro; /* format of protocol address */ 24 25 UCHAR arp_hln; /* length of hardware address */ 26 27 UCHAR arp_pln; /* length of protocol address */ 28 29 USHORT arp_op; /* ARP/RARP operation */ 30 31 UCHAR arp_sha[6]; /* sender hardware address */ 32 33 ULONG arp_spa; /* sender protocol address */ 34 35 UCHAR arp_tha[6]; /* target hardware address */ 36 37 ULONG arp_tpa; /* target protocol address */ 38 39 }ARPHEAD; 40 41 #pragma pack ()//字節對齊的控制
2. 注意網絡字節序和本機字節序的轉換。使用ntohs()等函數。下面是一個winpcap回調函數的例子,用來檢測本機是否在進行ARP掃描,對代碼有任何建議歡迎指出交流。
1 void packet_handler_ARP(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data) 2 { 3 struct tm *ltime; 4 ltime = new struct tm; 5 char timestr[16]; 6 time_t local_tv_sec; 7 time_t tTimer = time(0); 8 static unsigned short nNum; 9 10 if ( tTimer - g_tStartTimer > SNIFF_TIME)//計時嗅探時間 11 pcap_breakloop(g_OpenDev); 12 13 /* 將時間戳轉換成可識別的格式 */ 14 local_tv_sec = header->ts.tv_sec; 15 localtime_s(ltime, &local_tv_sec); 16 strftime( timestr, sizeof timestr, "%H:%M:%S", ltime); 17 18 printf("%s,%.6d len:%d\n", timestr, header->ts.tv_usec, header->len); 19 20 //嗅探自己是否發出了ARP 21 ETHERHEAD *pEtherHead = NULL; 22 pEtherHead = (ETHERHEAD*)pkt_data; 23 if ( strncmp((const char*)(pEtherHead->eh_src), (const char*)(g_aMac), 6) == 0) {//檢測源地址是否是本機 24 ARPHEAD *pARPHead = NULL; 25 //printf ("是本機發出的ARP數據"); 26 pARPHead = (ARPHEAD*)(pkt_data + sizeof(ETHERHEAD)); 27 if (ntohs (pARPHead->arp_pro) == 0x0800 &&//IP 28 ntohs(pARPHead->arp_op) == 0x0001 &&//ARP Request 29 (ntohl(pARPHead->arp_tpa) & 0xffff0000)== 0xc0a80000 ) {//是ARP請求內網IP 30 nNum ++; 31 //printf ("計數+1\n"); 32 if (nNum > WARN_NUM) {//計數超過了阈值參數 33 g_bWarning = true; 34 pcap_breakloop(g_OpenDev); 35 } 36 } 37 } 38 39 40 }