C++网络IP数据包监视

C++网络IP数据包监视

实现

main.cpp

#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#include "base.h"

WSADATA wsa_data;
SOCKET sniffer_socket = INVALID_SOCKET;
IP_PACKET packet;
char hostname[512];
hostent* local;
in_addr addr;
sockaddr_in src,dst;
DWORD optbuf[10];
DWORD optret;
DWORD optval = 1;
int addrlen = sizeof(sockaddr_in);
int ret;
int main(int argc,char* argv[])
{
	//初始化Windows Socket2
	ret = WSAStartup(MAKEWORD(2,2),&wsa_data);
	if(ret != 0)
	{
		printf("初始化Windows Socket2失败\n");
		return 1;
	}
	//创建套接字
	sniffer_socket = socket(AF_INET,SOCK_RAW,IPPROTO_IP);
	if(sniffer_socket == INVALID_SOCKET)
	{
		printf("创建套接字失败\n");
		WSACleanup();
		return 1;
	}
	//获取主机名
	ret = gethostname(hostname,sizeof(hostname));
	if(ret != 0)
	{
		printf("获取主机名失败\n");
		WSACleanup();
		return 1;
	}
	//获取本机IP地址
	local = gethostbyname(hostname);
	if(local == NULL)
	{
		printf("获取本机IP地址失败\n");
		WSACleanup();
		return 1;
	}
	printf("IP地址列表:\n");
	int i = 0;
	while(local->h_addr_list[i] != 0)
	{
		addr.S_un.S_addr = *(unsigned long*)local->h_addr_list[i];
		printf("\t%d:\t%s\n",i+1,inet_ntoa(addr));
		i++;
	}
	printf("请输入IP地址序号:\n");
	scanf("%d",&i);
	//将指定IP地址拷贝下来
	memset(&dst,0,sizeof(dst));
	memcpy(&dst.sin_addr.S_un.S_addr,local->h_addr_list[i-1],sizeof(dst.sin_addr.S_un.S_addr));
	//将套接字绑定在指定IP地址(端口由系统分配)上
	dst.sin_family = AF_INET;
	dst.sin_port = 0;
	ret = bind(sniffer_socket,(sockaddr*)&dst,sizeof(dst));
	if(ret == SOCKET_ERROR)
	{
		printf("绑定本地IP地址失败\n");
		WSACleanup();
		return 1;
	}
	//设置网卡为混杂模式,使套接字获取所有IP数据包
	ret = WSAIoctl(sniffer_socket,0x98000001,&optval,sizeof(optval),&optbuf,sizeof(optbuf),&optret,NULL,NULL);	//获取IP数据包,VC6.0没有SIO_RCVALL,故直接用0x98000001
	if(ret == SOCKET_ERROR)
	{
		printf("设置网卡为混杂模式失败\n");
		WSACleanup();
		return 1;
	}
	do
	{
		//接收IP数据包(阻塞模式)
		ret = recvfrom(sniffer_socket,(char*)&packet,sizeof(packet),0,(sockaddr*)&src,&addrlen);
		if(ret >0)
		{
			printf("\n");
			printf("获取到IP数据包\n");
			printf("源IP地址:%s\n",inet_ntoa(packet.IPHeader.Src));
			printf("目的IP地址:%s\n",inet_ntoa(packet.IPHeader.Dst));
			printf("IP头长度:%d\n",packet.IPHeader.Len);
			printf("数据包长度:%d\n",packet.IPHeader.TotLen);
			printf("协议:%s\n",GetProtocol(&packet.IPHeader));
		}
		else
		{
			printf("接收数据包失败\n");
			WSACleanup();
			return 1;
		}
	}while(true);
	WSACleanup();
	return 0;
}

base.h

#ifndef _BASE_H
#define _BASE_H
typedef struct tagIP_HEADER	//IP头
{
	unsigned char Len:4;
	unsigned char Ver:4;
	unsigned char TOS;
	unsigned short TotLen;
	unsigned short ID;
	unsigned short FlagOff;
	unsigned char TTL;
	unsigned char Protocol;
	unsigned short Checksum;
	in_addr Src;
	in_addr Dst;
}IP_HEADER, *LPIP_HEADER;
#pragma pack(push)	//将当前对齐字节压入栈
#pragma pack(1)		//使对齐字节为1,防止IP_PACKET对齐4字节
typedef struct tagIP_PACKET	//IP数据包
{
	IP_HEADER IPHeader;
	char data[65515];
}IP_PACKET, *LPIP_PACKET;
#pragma pack(pop)	//恢复对齐字节
const char* strTCP = "TCP协议";
const char* strUDP = "UDP协议";
const char* strICMP = "ICMP协议";
const char* strUnknown = "未知协议";
const char* GetProtocol(LPIP_HEADER iphdr)	//返回协议字符串
{
	switch(iphdr->Protocol)
	{
	case 1:
		return strICMP;
		break;
	case 6:
		return strTCP;
		break;
	case 17:
		return strUDP;
		break;
	default:
		return strUnknown;
		break;
	}
}
#endif
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值