一、链路层数据格式

mac报文:14个字节

二、IP数据报文格式

三、TCP数据报文格式

四、UDP数据报文格式

五、demo(网络分析器)

recvfrom接收链路层帧数据,不经过网络层、传输层,不会给发送者的地址结构赋值,因此后两个参数为NULL。

设计思路:

①创建一个原始套接字。
②while(1)利用recvfrom不断接收网络数据。
③解析获得mac头部中的源mac和目的mac,并判断网络层的协议类型。
④若是IP报文,则获得源IP和目的IP,并解析获得传输层协议类型。
⑤若传输层为TCP或UDP协议,则解析报文获得数据

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/ether.h>
#include <arpa/inet.h>
#include <errno.h>int main()
{//1.创建一个原始套接字(ETH_P_ALL表示收发任何数据类型)int sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));if(sockfd<0){perror("socket");return 0;}else{printf("sockfd=%d\n",sockfd);}//2.使用recvfrom接收网络数据(数据多,需要用while)while(1){//定义buf存放帧数据,大小unsigned char1500unsigned char buf[1500]="";int len = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);printf("len= %d\n",len);/*buf不要用%s遍历。帧数据大多都是不可识别的ASCII值,有太多的0x00;不可sleep(),当休眠时有速度过来,数据会被协议栈提取一层一层往上走,对于链路层就没有了,会丢失数据。*//*解析buf中的mac头部信息。[mac][ip][tcp/udp][data]  eg:ff:ff:ff:ff:ff:ff 长度2*6+5+1=18mac头部结构:目的mac(6B) 源mac(6B) 类型(2B) */char src_mac[18]="";              char dst_mac[18]="";sprintf(dst_mac,"%02x:%02x:02x:02x:02x:02x:",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]); //组目的macsprintf(src_mac,"%02x:%02x:02x:02x:02x:02x:",buf[0+6],buf[1+6],buf[2+6],buf[3+6],buf[4+6],buf[5+6]); //组源的macprintf("%s--->%s\n", src_mac, dst_mac);//判断mac头部中的协议类型 (IP:0x0800 ARP:0X0806 RARP:0x8035)unsigned short mac_type = ntohs(*(unsigned short *)(buf+12));   //取出后为网络字节序,需转成主机字节序if( mac_type == 0x0800 ){printf("mac_type = %#x IP报文\n", mac_type);              //%#X,会在打印的十六进制结果前面加上0X//分析IP头部unsigned char *ip_addr = buf+14;        //+14为了跳过mac头//ip_addr跳到源IP的起始位置ip_addr += 12;                           //跳过3行,一行4字节char src_ip[16]="";char dst_ip[16]="";sprintf(src_ip,"%d.%d.%d.%d",ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]);             //源IPip_addr +=4;sprintf(dst_ip,"%d.%d.%d.%d",ip_addr[0],ip_addr[1],ip_addr[2],ip_addr[3]);             //目的IPprintf("%s--->%s\n", src_ip, dst_ip);//判断网络层的上一层协议类型ip_addr = buf+14;                          //跳回IP起始位置unsigned char *ip_type = ip_addr + 9;       //跳到协议类型位置if(*ip_type == 1){printf("ICMP报文\n");}else if(*ip_type == 2){printf("IGMP报文\n");}else if(*ip_type == 6){printf("TCP报文\n");ip_addr = buf + 14;       //回到IP起始位置int ip_head_len = (*ip_addr&0x0f)*4;                 //获得IP报文头部长度(&0x0f目的为了获得低八位)unsigned char *tcp_addr = buf + 14 + ip_head_len;      //tcp_addr:TCP起始位置unsigned src_port = ntohs(*(unsigned short *)tcp_addr);       //获取源端口unsigned dst_port = ntohs(*(unsigned short *)(tcp_addr+2));    //获取目的端口//打印printf("%hu--->%hu\n",src_port,dst_port);//跳到TCP首部长度的位置unsigned char *tcp_headLen_addr = tcp_addr+12;int tcp_head_len = (*tcp_headLen_addr>>4)&0x0f;      //高4位移动到低4位后再取//打印数据printf("TCP:%s\n",tcp_addr + tcp_head_len);}else if(*ip_type == 17){printf("UDP报文\n");ip_addr = buf + 14;       //回到IP起始位置int ip_head_len = (*ip_addr&0x0f)*4;                 //获得IP报文头部长度(&0x0f目的为了获得低位数据)unsigned char *udp_addr = buf + 14 + ip_head_len;     //udp_addr:UDP起始位置unsigned src_port = ntohs(*(unsigned short *)udp_addr);       //获取源端口unsigned dst_port = ntohs(*(unsigned short *)(udp_addr+2));    //获取目的端口//打印printf("%hu--->%hu\n",src_port,dst_port);//打印数据printf("UDP:%s\n",udp_addr+8);    //应用层数据}}else if(mac_type == 0x0806 ){printf("mac_type = %#x ARP报文\n", mac_type);}else if(mac_type == 0x8035 ){printf("mac_type = %#x RARP报文\n", mac_type);}}//关闭套接字close(sockfd);return 0;
}

测试:sudo运行.out文件

利用C语言编写一个网络分析器相关推荐

  1. 利用c语言编写一个时钟计时器(c语言基础练习)

    时间对于每个人都是宝贵的.人类从古至今都在发展计时设备和改善计时方法.远古时期,人类根据太阳和月亮的位置来判断时间.根据影子的方向长短来区分早晨.中午和黄昏.古代人也发明了很多计时的方法,日晷.沙漏. ...

  2. 建立网络链接编程C语言,用C语言编写一个网络蜘蛛来搜索网上出现的电子邮件地址...

    可能大家经常要去互联网上搜索特定的内容,比如收集大量邮件地址,如果用google之类的搜索引擎是没法实现这种特定功能的,所以用C语言来写一个吧.它的功能就是不断去取得网络上的页面,然后分析出网页上出现 ...

  3. [转]用 C 语言编写一个网络蜘蛛

    用 C 语言编写一个网络蜘蛛来搜索网上出现的电子邮件地址 作者:zhoulifa 来源:http://bbs.chinaunix.net/viewthread.php?tid=821361 可能大家经 ...

  4. 利用Java语言编写一个猜数字游戏(有次数限制)

    猜数字小游戏. 利用Java语言编写. 题目: 用代码模拟猜数字的小游戏. 思路: 1.首先需要产生一个随机数字,并且一旦产生不再变化.用Random的nextInt方法 2.需要键盘输入,所以用到了 ...

  5. java语言编写计算器_第二次作业利用java语言编写计算器进行四则运算

    随着第一次作业的完成,助教 牛老师又布置了第二次作业:用java语言编写一个程序然后进行四则运算用户用键盘输入一个字符来结束程序显示统计结果.一开始看到这个题目我也着实吓了一跳 因为不知道如何下手而且 ...

  6. c语言编写一个简单的答题系统

    利用c语言编写一个简单的答题系统. 思路是先设计好题目和答案,再输入自己的答案,利用输入的答案与正确答案对比,从而得出你回答的对错. (一)捆绑题目和答案 我们可以利用结构体对一个题目捆绑上一个答案. ...

  7. 使用Java语言编写一个五子棋UI界面并实现网络对战功能(非局域网)

    使用Java语言编写一个五子棋UI界面并实现网络对战功能(非局域网) 一,前期准备 1,Java IDE(Eclipse)与JDK的安装与配置 jdk-15.0.1-免配置路径版 提取码:earu 免 ...

  8. 用C语言用指针怎么算通用定积分,C语言:利用函数指针编写一个用矩形法求定积分的通用函数,包括正弦,余弦和指数函数,...

    问题描述: C语言:利用函数指针编写一个用矩形法求定积分的通用函数,包括正弦,余弦和指数函数, //我运行的结果和答案对不上,请帮我看看程序对吗? //实现积分 #include #include i ...

  9. 编写指数函数 c语言,C语言:利用函数指针编写一个用矩形法求定积分的通用函数,包括正弦,余弦和指数函数,...

    问题描述: C语言:利用函数指针编写一个用矩形法求定积分的通用函数,包括正弦,余弦和指数函数, //我运行的结果和答案对不上,请帮我看看程序对吗? //实现积分 #include #include i ...

最新文章

  1. 递归和迭代的区别是什么,各有什么优缺点?
  2. Java数组的基本操作方法整理
  3. 【Python基础】Python开发环境设置和小技巧
  4. Git知识总览(六) Git分支中的远程操作实践
  5. 科研实习 | 北京大学智能学院贺笛老师招收NLP/GNN方向科研实习生
  6. python笔记之while和for循环练习
  7. SSIS常用的包—大量插入任务(Bulk Insert task)
  8. 前排!零基础小白学习3D建模的必经之路
  9. Matlab图像分割---使用主动轮廓 (snake) 方法进行图像分割
  10. 故障树手册(Fault Tree handbook)(5)
  11. O3 Interchange全面讲解
  12. [NeRF]学习笔记(持续更新中)
  13. 在win7 上安装 Visual Studio 2019 步骤 及 vs2019离线安装包
  14. 麒麟合盛(APUS)李涛:APUS云重新定义“云联邦”
  15. keilC51编译常见错误和警告说明
  16. PyTorch+YOLOv5环境搭建(未完待续)
  17. 测试平台开发:(14)测试用例管理功能设计
  18. 大华乐橙云JavaWEB版实现网页直播远程监控DEMO
  19. RK3568平台开发系列讲解(音视频篇)AudioTrack音频流数据传输
  20. 适配Oracle版本的ojbc驱动包版本,以及ojdbc驱动包的下载地址

热门文章

  1. Unity Cinemachine插件全功能详解
  2. 希望计算机专业学生都知道这些宝藏老师
  3. linuxprobe第一章
  4. 每日英语--Week 1
  5. 肯德基宅急送,你值得学习的滚动屏
  6. JavaScript组合函数
  7. rtthread AT指令下发程序
  8. 新导养老院的老年人定位系统的应用
  9. Linux中的xargs命令(这是我发现的对于xargs命令的最好解释)
  10. 数据结构——优先级队列(堆)