1.题目描述
参照 raw socket 编程例子,设计一个可以监视网络的状态、数据流动情况以及网络上传输 的信息的网络嗅探器。
2.运行结果
3.导入程序需要的库
请参考下面链接:
导入WinPcap到Clion (2024)-CSDN博客
4.参考代码
#define HAVE_REMOTE
#define LINE_LEN 16#include "winsock.h"
#include <WinSock2.h>
#include <string>
#include <cstdio>
#include <pcap.h>
#include <sys/time.h>
#include <iostream>#pragma comment(lib, "ws2_32.lib")
using namespace std;typedef struct ip_address { //ip地址u_char b1;u_char b2;u_char b3;u_char b4;
} ip_address;typedef struct mac_address {//mac地址u_char b1;u_char b2;u_char b3;u_char b4;u_char b5;u_char b6;
} mac_address;typedef struct ethe_header { //mac帧首部mac_address mac_dest_address;mac_address mac_source_address;u_short ether_type;
} ethe_header;typedef struct ip_header { //ip地址首部u_char ver_ihl;u_char tos;u_short tlen;u_short identification;u_short flags_fo;u_char ttl;u_char proto;u_short crc;ip_address saddr;ip_address daddr;u_int op_pad;
} ip_header;typedef struct udp_header { //UPD首部u_short sport;u_short dport;u_short len;u_short crc;
} udp_header;typedef struct tcp_header { //TCP首部u_short sport;u_short dport;u_int num;u_int ack;u_short sum;u_short windonw;u_short crc;u_short ugr;
} tcp_header;void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data);char judge;
int length;int main() {cout << " *============网络报文捕获程序的设计与实现Demo============*" << endl << endl;pcap_if_t *alldevs, *device;int i = 0;int iNum;u_int netmask;struct bpf_program fcode;pcap_t *adhandle;char errbuf[PCAP_ERRBUF_SIZE];//修改这里可以更改捕获的数据包使用的协议类型char packet_filter[] = "(ip and udp) or (ip and tcp) or (ip and icmp)";//获取设备列表if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1) {fprintf(stderr, "无法打开网络设备:%s\n", errbuf);return 1;}for (device = alldevs; device != NULL; device = device->next) { //打印列表if (i == 0) {printf("------------------------------网络设备-------------------------------\n");}if (device->description)printf(" 序号:%d (%s)\n", ++i ,device->description);else{i++;printf("没有设备描述信息!");}}if (i == 0) {printf("\n请先安装WinPcap!");return -1;}printf("-------------------------------------------------------------------\n");printf("\n请选择网络设备接口:(1 - %d):", i);scanf("%d", &iNum);getchar();if (iNum < 1 || iNum > i) {printf("设备不存在!\n");pcap_freealldevs(alldevs);return -1;}//跳转到已选设备for (device = alldevs, i = 0; i < iNum - 1; device = device->next, i++);// 打开适配器if ((adhandle = pcap_open(device->name, // 设备名65536, // 要捕捉的数据包的部分// 65535保证能捕获到不同数据链路层上的每个数据包的全部内容PCAP_OPENFLAG_PROMISCUOUS, // 混杂模式1000, // 读取超时时间NULL, // 远程机器验证errbuf // 错误缓冲池)) == NULL) {fprintf(stderr, "\n不能打开适配器!\n");/* 释放设备列表 */pcap_freealldevs(alldevs);return -1;}if (pcap_datalink(adhandle) != DLT_EN10MB) { //检查数据链路层,为了简单,只考虑以太网fprintf(stderr, "\n系统网卡链路出错!\n");pcap_freealldevs(alldevs); //释放设备列表return -1;}if (device->addresses != NULL) //获得接口第一个地址的掩码netmask = ((struct sockaddr_in *) (device->addresses->netmask))->sin_addr.S_un.S_addr;else //如果接口没有地址,那么我们假设一个C类的掩码netmask = 0xffff00;if (pcap_compile(adhandle, &fcode, packet_filter, 1, netmask) < 0) { //编译过滤器fprintf(stderr, "不能监听过滤该数据报!\n");pcap_freealldevs(alldevs);return -1;}if (pcap_setfilter(adhandle, &fcode) < 0) { //设置过滤器fprintf(stderr, "过滤设置错误!\n");pcap_freealldevs(alldevs);return -1;}printf(" 是否要输出报文数据(y/n) : ");scanf("%c", &judge);if (judge != 'n') {printf("请输入要限制要输出报文信息长度(-1不限制) : ");scanf("%d", &length);}printf("\n\n 正在监听通过%s的数据报...\n\n", device->description);pcap_freealldevs(alldevs); //释放设备列表pcap_loop(adhandle, 0, packet_handler, NULL); //开始捕捉return 0;
}void packet_handler(u_char *dumpfile, const struct pcap_pkthdr *header,const u_char *pkt_data) { //回调函数,当收到每一个数据包时会被libpcap所调用if (header->caplen > 400) return;int len;struct tm *ltime;char timestr[16];ip_header *ip_hd;udp_header *udp_hd;tcp_header *tcp_hd;ethe_header *ethe_hd;int ip_len, tcp_len, start;u_short sport, dport;printf("\n");char now[64];struct tm *ttime;time_t tt;tt = header->ts.tv_sec;ttime = localtime(&tt);strftime(now,64,"%Y-%m-%d %H:%M:%S",ttime);printf("\t时间:%s\n", now);ethe_hd = (ethe_header *) pkt_data;ip_hd = (ip_header *) (pkt_data + 14);ip_len = (ip_hd->ver_ihl & 0xf) * 4; //ip首部长度udp_hd = (udp_header *) ((u_char *) ip_hd + ip_len);sport = ntohs(udp_hd->sport);dport = ntohs(udp_hd->dport);if (ip_hd->proto == 17) {printf("\t协议:UDP");start = ip_len + 8;} else if (ip_hd->proto == 6) {printf("\t协议:TCP");tcp_hd = (tcp_header *) ((u_char *) ip_hd + ip_len);tcp_len = ntohs(tcp_hd->sum) >> 12;start = ip_len + tcp_len * 4;} else if (ip_hd->proto == 1) {printf("\t协议:ICMP");start = ip_len + 23;} else printf("\t协议:其他");//printf("start=%d\n",start);printf("\t\t\t数据报的长度: %d\n", header->caplen);printf("\tIP头的长度: %d""\t\tIP包存活时间: %d\n", ip_hd->tlen, ip_hd->ttl);printf("\t源IP地址: %d.%d.%d.%d:%d""\t目的IP地址: %d.%d.%d.%d:%d\n""\t源端口: %d""\t\t\t目的端口: %d\n""\t源物理地址: %x-%x-%x-%x-%x-%x""\t目的物理地址: %x-%x-%x-%x-%x-%x\n",ip_hd->saddr.b1, ip_hd->saddr.b2, ip_hd->saddr.b3, ip_hd->saddr.b4,ip_hd->daddr.b1, ip_hd->daddr.b2, ip_hd->daddr.b3, ip_hd->daddr.b4, sport, dport,ethe_hd->mac_source_address.b1, ethe_hd->mac_source_address.b2, ethe_hd->mac_source_address.b3,ethe_hd->mac_source_address.b4, ethe_hd->mac_source_address.b5, ethe_hd->mac_source_address.b6,ethe_hd->mac_dest_address.b1, ethe_hd->mac_dest_address.b2, ethe_hd->mac_dest_address.b3,ethe_hd->mac_dest_address.b4, ethe_hd->mac_dest_address.b5, ethe_hd->mac_dest_address.b6);//输出数据部分if (judge == 'y') {printf("\n\t数据部分内容为:\n\t");if (length == -1) len = (header->caplen) + 1;else len = (length > header->caplen + 1 - start) ? (header->caplen + 1) - start : length;for (int i = start; (i < start + len); i++) {printf("%2.2x ", pkt_data[i - 1]); //也可以改为 %c 以 ascii码形式输出。if ((i % LINE_LEN) == 0) printf("\n\t");}}cout<<endl<<"---------------------------------------------------------------------"<<endl;
}
2024 HNUST计算机网络课程设计-(ᕑᗢᓫ∗)˒芒果酱-参考文章
(代码可以参考,૮₍ ˃ ⤙ ˂ ₎ა 但同学们要认真编写哦)
-------------------------------------------------------------------------
1、网络聊天程序的设计与实现
C++ Socket 多线程 网络聊天室 支持用户端双向交流(2023)-CSDN博客
2、Tracert 与 Ping 程序设计与实现
Tracert 与 Ping 程序设计与实现(2024)-CSDN博客
3、滑动窗口协议仿真
滑动窗口协议仿真(2024)-CSDN博客
4、OSPF 路由协议原型系统设计与实现
OSPF 路由协议原型系统设计与实现-CSDN博客
5、基于 IP 多播的网络会议程序
基于 IP 多播的网络会议程序(2024)-CSDN博客
6、编程模拟 NAT 网络地址转换
编程模拟 NAT 网络地址转换(2024)-CSDN博客
7、网络嗅探器的设计与实现
网络嗅探器的设计与实现(2024)-转载-CSDN博客
8、网络报文分析程序的设计与实现
网络报文分析程序的设计与实现(2024)-CSDN博客
9、简单 Web Server 程序的设计与实现
简单 Web Server 程序的设计与实现 (2024)-CSDN博客
10、路由器查表过程模拟计算机网络 - 路由器查表过程模拟 C++(2024)-CSDN博客