参照附录 4 raw socket 编程例子,设计一个可以监视网络的状态、数据流动情况以及网络上传输 的信息的网络嗅探器。
显示了流量信息,若要查看报文信息请修改注释。
自动获取ip
#include <iostream>
#include <winsock2.h>
#include <time.h>
#pragma comment(lib, "WS2_32")
using namespace std;
void DecodeIPPacket(char *pData);
void DecodeTCPPacket(char *pData);
void DecodeUDPPacket(char *pData);
void DecodeICMPPacket(char *pData);
#define SIO_RCVALL _WSAIOW(IOC_VENDOR,1)
double all=0;
/*****IP分组首部结构******/
//IP首部结构
typedef struct _IPHeader {
unsigned char iphVerLen; // 版本号和头长度各占4位
unsigned char ipTOS; // 服务类型
unsigned short ipLength; // 分组总长度
unsigned short ipID; //分组标识,惟一标识发送的每一个数据报
unsigned short ipFlags; // 标志
unsigned char ipTTL; // 生存时间,TTL
unsigned char ipProtocol; // 协议可以是TCP、UDP、ICMP等
unsigned short ipChecksum; // 校验和
unsigned long ipSource; // 源IP地址
unsigned long ipDestination; // 目的IP地址
} IPHeader, *PIPHeader;
//ICMP报头结构******/
typedef struct icmphdr {
char i_type; //8 位类型字段
char i_code; //8 位代码字段
unsigned short i_cksum; //16位校验和
unsigned short i_id; //标识符,一般可设为发送进程的ID
unsigned short i_seq; //序列号
unsigned long timestamp; //时间戳
} ICMPHeader;
//UDP报头结构
typedef struct _UDPHeader {
unsigned short sourcePort; // 源端口号
unsigned short destinationPort; // 目的端口号
unsigned short len; // 包长度
unsigned short checksum; // 校验和
} UDPHeader;
//TCP报头结构
typedef struct _TCPHeader {
unsigned short sourcePort; // 16位源端口号
unsigned short destinationPort; // 16位目的端口号
unsigned long sequenceNumber; // 32位序列号
unsigned long acknowledgeNumber; // 32位确认号
char dataoffset; //高4位表示数据偏移
char flags; //低6位为URG、ACK、PSH、RST、SYNhe FIN六个标志位
unsigned short windows; // 16位窗口大小
unsigned short checksum; // 16位校验和
unsigned short urgentPointer; // 16位紧急数据偏移量
} TCPHeader;
int main() {
setvbuf(stdout, NULL, _IONBF, 0);
WSADATA wsaData; // 用来存储被WSAStartup函数调用后返回的Windows Sockets数据
WSAStartup(MAKEWORD(2, 2), &wsaData); // 完成对Winsock服务的初始化
/**** 创建原始套节字 IPv4 TCP******/
SOCKET sRaw = socket(PF_INET, SOCK_RAW, 0);
SOCKADDR_IN addr_in; // 目的地址
/*****输入想要要监听的接口的IP地址******/
//cout << "请输入要监听接口的IP地址:";
char snfIP[20];
//cin.getline(snfIP, sizeof(snfIP));
char hostname[256];
gethostname(hostname,sizeof(hostname)); //获取主机信息
HOSTENT* host=gethostbyname(hostname);
strcpy(snfIP,inet_ntoa(*(in_addr*)*host->h_addr_list)); //copy主机信息中的ip到snfIP
addr_in.sin_family = AF_INET; // IPv4
addr_in.sin_port = htons(80); // 80端口
addr_in.sin_addr.S_un.S_addr = inet_addr(snfIP); // 监听的地址
/****绑定网卡IP地址******/
bind(sRaw, (PSOCKADDR) &addr_in, sizeof(addr_in));
/****在调用ioctlsocket将网卡设为混杂模式前,套节字必须绑定该网卡的IP地址******/
DWORD dwValue = 1;
// 套接字 SIO_RCVALL操作为所有的IP包无论经不经过
ioctlsocket(sRaw, SIO_RCVALL, &dwValue);
// 开始抓取IP分组
char buff[50][4096];
int packetNumber;
int time=0;
while (1) {
long t=clock();
double v=0.0;
recv(sRaw, buff[0], 4096, 0);
//cout << endl;
DecodeIPPacket(buff[0]);//解析IP包
//cout <<clock()-t<< endl;
time+=clock()-t;
if(time>1000){
v=all/1024;
//cout <<all<<"Bytes/s"<< endl;
printf("%.02fKB/s\n",v);
all=0;
time=0;
}
//v=(all-a)/((clock()-t)*1000);
//cout <<v <<"bytes/s"<< endl;
}
closesocket(sRaw);
WSACleanup();
return 0;
}
/**********IP分组解析函数*************/
void DecodeIPPacket(char *pData) {
int n = 0;
IPHeader *pIPHdr = (IPHeader *) pData;
// 源地址和目的地址
in_addr source, dest;
char szSourceIp[32], szDestIp[32];
/***从IP头中取出源IP地址和目的IP地址***/
source.S_un.S_addr = pIPHdr->ipSource; // 设置源地址
dest.S_un.S_addr = pIPHdr->ipDestination; // 设置目的地址
strcpy(szSourceIp, inet_ntoa(source));
strcpy(szDestIp, inet_ntoa(dest));
/* cout << "源IP:" << szSourceIp;
cout << "目的IP: " << szDestIp << endl;*/
int nHeaderLen = (pIPHdr->iphVerLen & 0xf) * sizeof(ULONG);// IP头长度
// cout << "大小:" << ntohs(pIPHdr->ipLength) << endl;
all+=ntohs(pIPHdr->ipLength);
switch (pIPHdr->ipProtocol) // 协议
{
case IPPROTO_TCP: // 调用函数解析TCP包
DecodeTCPPacket(pData + nHeaderLen);
break;
case IPPROTO_UDP:// 调用函数解析UDP包
DecodeUDPPacket(pData + nHeaderLen);
break;
case IPPROTO_ICMP:// 调用函数解析ICMP包
DecodeICMPPacket(pData + nHeaderLen);
break;
default:
cout << " 协议号:" << (int) pIPHdr->ipProtocol << endl;
}
}
/*********TCP包解析函数***********/
void DecodeTCPPacket(char *pData) {
TCPHeader *pTCPHdr = (TCPHeader *) pData;
/*cout << "TCP Source Port: " << ntohs(pTCPHdr->sourcePort);
cout << " Destination Port: " << ntohs(pTCPHdr->destinationPort) << endl;
cout << pTCPHdr ->windows<<endl;*/
}
/***********UDP包解析函数**********/
void DecodeUDPPacket(char *pData) {
UDPHeader *pUDPHdr = (UDPHeader *) pData;
/* cout << "UDP Source Port: " << ntohs(pUDPHdr->sourcePort);
cout << " Destination Port: " << ntohs(pUDPHdr->destinationPort) << endl;*/
//cout << ntohs(pUDPHdr ->len)<<endl;
}
/***********ICMP包解析函数 **********/
void DecodeICMPPacket(char *pData) {
ICMPHeader *pICMPHdr = (ICMPHeader *) pData;
cout << "ICMP Type: " << pICMPHdr->i_type << "Code: " << pICMPHdr->i_code << endl;
switch (pICMPHdr->i_type) {
case 0:
cout << "Echo Response.\n";
break;
case 8:
cout << "Echo Request.\n";
break;
case 3:
cout << "Destination Unreachable.\n";
break;
case 11:
cout << "Datagram Timeout(TTL=0).\n";
break;
}
}
``