C/C++网络编程时注意的问题小结
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 }