概述
#include <winsock2.h>
#include <windows.h>
#include <mstcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#include <iostream>
using namespace std;
//IP首部
typedef struct tIPPackHead
{
enum PROTOCOL_TYPE{
PROTOCOL_TCP = 6,
PROTOCOL_UDP = 17,
PROTOCOL_ICMP = 1,
PROTOCOL_IGMP = 2
};
inline unsigned HeadLen() const
{
//首部长度单位为4bytes。因此乘4
return (ver_hlen & 0x0F) << 2;
}
inline unsigned PackLen() const
{
return wPacketLen;
}
BYTE ver_hlen;
//IP协议版本和IP首部长度。高4位为版本,低4位为首部的长度(单位为4bytes)
BYTE byTOS;
//服务类型
WORD wPacketLen; //IP包总长度。包括首部,单位为byte。[Big endian]
WORD wSequence;
//序号,一般每个IP包的序号递增。[Big endian]
WORD wMarkFragPoi;
BYTE byTTL;
//生存时间
BYTE byProtocolType; //协议类型,见PROTOCOL_TYPE定义
WORD wHeadCheckSum;
//IP首部校验和[Big endian]
DWORD dwIPSrc;
//源地址
DWORD dwIPDes;
//目的地址
} IP_PK_HEAD;
int DecodeIP(char *buf, int len);
int DecodeIP(char *buf, int len)
{
int n = len;
if( n >= sizeof(IP_PK_HEAD) )
{
IP_PK_HEAD iphead;
memcpy( &iphead, buf, sizeof(iphead) );
//以下三个为Big Endian字节顺序,转换成主机字节顺序
iphead.wPacketLen = ntohs( iphead.wPacketLen );
iphead.wSequence = ntohs( iphead.wSequence );
iphead.wHeadCheckSum = ntohs( iphead.wHeadCheckSum );
in_addr src,dst;
src.S_un.S_addr = iphead.dwIPSrc;
dst.S_un.S_addr = iphead.dwIPDes;
char strsrc[20],strdst[20];
strcpy(strsrc, inet_ntoa(src));
strcpy( strdst , inet_ntoa(dst));
printf( "IP数据包: ver=%d,hlen=%d,protocol=%d,pklen=%d,seq=%d,src=%s,dst=%s _fcksavedurl=%s,dst=%s",
iphead.ver_hlen >> 4,
(iphead.ver_hlen & 0x0F) << 2,
iphead.byProtocolType,
iphead.wPacketLen,
iphead.wSequence,
strsrc,
strdst );
}
return 0;
}
void AutoWSACleanup()
{
::WSACleanup();
}
int main()
{
//初始化winsock库,使用2.2版本
u_short wVersionRequested = 0x0202;
WSADATA wsaData;
if( SOCKET_ERROR == WSAStartup( wVersionRequested, &wsaData ) )
{
cout << WSAGetLastError();
return 0;
}
atexit( AutoWSACleanup );
//创建SOCKET
SOCKET h = socket( AF_INET, SOCK_RAW, IPPROTO_IP);
if( h == INVALID_SOCKET )
{
cout << WSAGetLastError();
return 0;
}
//获取本机地址
char FAR name[128];
if( -1 == gethostname(name, sizeof(name)) )
{
closesocket( h );
cout << WSAGetLastError();
return 0;
}
struct hostent FAR * pHostent;
pHostent = gethostbyname(name);
//绑定本地地址到SOCKET句柄
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr = *(in_addr*)pHostent->h_addr; //IP
addr.sin_port = 0; //端口,IP层端口可随意填
if( SOCKET_ERROR == bind( h,(sockaddr *)&addr,sizeof(addr) ) )
{
closesocket( h );
cout << WSAGetLastError();
return 0;
}
//设置该SOCKET为接收所有流经绑定的IP的网卡的所有数据,包括接收和发送的数据包
//该函数在mstcpip.h里面,详见MSDN帮助
u_long sioarg = 1;
DWORD wt=0;
if( SOCKET_ERROR == WSAIoctl( h, SIO_RCVALL , &sioarg,sizeof(sioarg),NULL,0,&wt,NULL,NULL ) )
{
closesocket( h );
cout << WSAGetLastError();
return 0;
}
//我们只需要接收数据,因此设置为阻塞IO,使用最简单的IO模型
u_long bioarg =
0;
if( SOCKET_ERROR == ioctlsocket( h, FIONBIO , &bioarg ) )
{
closesocket( h );
cout << WSAGetLastError();
return 0;
}
//开始接收数据
//因为前面已经设置为阻塞IO,recv在接收到数据前不会返回。
//当返回<=0时表示接收失败,退出循环
//可以在另一个线程执行此循环,主线程closesocket可以使recv失败而结束循环
char buf[102400];
int len = 0;
do
{
len = recv( h, buf, sizeof(buf),0);
if( len > 0 )
{
DecodeIP( buf, len );
}
}while( len > 0 );
closesocket( h );
return 0;
}
最后
以上就是多情雪碧为你收集整理的基于VC6.0的抓取TCP/IP数据包的C++实现的全部内容,希望文章能够帮你解决基于VC6.0的抓取TCP/IP数据包的C++实现所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复