不知道大家是否使用过网络数据抓包工具WireShark,Wireshark能够捕捉出入网卡的每一帧网络包,并能够详细列出网络包的源IP地址、目的IP地址、端口号、协议类型以及数据内容等信息。在数据(Data)一栏,Wireshark按照下图样式将数据(Data)按十六进制以及字符的形式打印出来。这样的打印信息清晰而明了,下面我们就来编写一个格式化数据输出函数hexdump吧。
void hexdump (char *buf, int len) { register int m; register int n; register char *data; data=buf; for (m=0;m<len;m++) { if( (!(m%2)) && (m!=0) ) fprintf (stderr, " "); if( (!(m%20)) && (m!=0) ) { for (n=20;n>0;n--) { if ((*(data+m-n)>31) && (*(data+m-n)<127)) fprintf (stderr, "%c", *(data+m-n)); else fprintf (stderr, "."); } fprintf (stderr, "\n"); } fprintf (stderr, "%02x",*(data+m)); } for (m=0;m<(20-((len%20)?(len%20):20))*2+(10-((len%20)?(len%20-1):19)/2);m++) fprintf (stderr, " "); for (m=len-((len%20)?(len%20):20);m<len;m++) { if ((*(data+m)>31) && (*(data+m)<127)) fprintf (stderr, "%c", *(data+m)); else fprintf (stderr, "."); } fprintf (stderr, "\n\n"); }
注释:
1、register这个关键字告诉编译器尽可能的将变量存在CPU内部寄存器中而不是通过内存寻址访问以提高效率。
2、因为ASCII码中的可显字符范围是32得到126,所以才有了“if ((*(data+m-n)>31) && (*(data+m-n)<127))”这一行,其他不可见的控制字符用“.”代替打印出来。
运行结果示例:
4861 6965 7200 0069 1500 0000 0000 0000 0000 0000 Haier..i............ 3836 3065 6236 3961 6361 6539 3900 0000 0031 2e30 860eb69acae99....1.0 2e30 0000 0055 4449 5343 4f56 4552 595f 5041 4400 .0...UDISCOVERY_PAD. 0000 0000 0000 0000 0000 0000 0000 0000 00 .................
除非注明,文章均为CppLive 编程在线原创,转载请注明出处,谢谢。
🙂 void hexdump (char *buf, int len) 中的buf从哪里来?是自己保存文本然后去open 、read?
通常是这种情况:客户端与服务端之间建立了一个TCP连接,其中一方收到另一方发来的数据时,从Socket里面read所有数据存入一个临时buf,为了直观分析buf中的数据才调用该函数罗根哥~
牛逼
😳