Windows下通过使用RAW原始套接字进行抓包

// 注意:原始套接字只在系统管理员权限下起作用,其它情况下socket创建失败,所以开发时首先以管理员权限启动VS

SOCKET nAnniSock = socket(AF_INET, SOCK_RAW, IPPROTO_IP);  // 指定为原始套接字(IP层抓取)


// 设置IP_HDRINCL选项,以便自己构造(解析)IP头部

BOOL bRaw = TRUE;

setsockopt(nAnniSock, IPPROTO_IP, IP_HDRINCL, (const char*)&bRaw, sizeof(bRaw));


// socket本地信息

sockaddr_in stAnniSock;
stAnniSock.sin_family = AF_INET;
stAnniSock.sin_port = htons(0); // 设置为任意端口

// 不设置IP地址会导致后面bind失败,设置为INADDR_ANY的话后面的WSAIoctl会产生参数错误而失败
// 所以只能设置为指定网卡的IP地址(据说设置无线网卡的IP地址也会失败)

stAnniSock.sin_addr.S_un.S_addr = htonl(0xc0a8010a); //htonl(INADDR_ANY);


// 绑定套接字,如果不绑定则后面的recvfrom会立即返回空值
bind(nAnniSock, (sockaddr*)&stAnniSock, sizeof(stAnniSock));

// 设置套接字接收所有数据包(混杂模式)(必须在bind之后调用),#define SIO_RCVALL  (IOC_IN|IOC_VENDOR|1)
DWORD uiOptval = 1;
char charRecv[10];
DWORD dwBytesRet = 0;
WSAIoctl(nAnniSock, (IOC_IN | IOC_VENDOR | 1), &uiOptval, sizeof(uiOptval), charRecv, sizeof(charRecv), &dwBytesRet, NULL, NULL);


// socket发送源信息
sockaddr_in stSockCamera;

int nLen = sizeof(sockaddr_in);
// 超时设定
timeval timeoutonce;
timeoutonce.tv_sec = 1;

timeoutonce.tv_usec = 0;


// 循环接收

while(TRUE)

{

// 调用select前需要从新设置,否则可能只有第一次select到数据包后,以后select就不管用了
fd_set udpSetAnni;
FD_ZERO(&udpSetAnni);
FD_SET(nAnniSock, &udpSetAnni);

// 调用select函数检查是否有数据包到达,否则直接用recvfrom会导致阻塞

if (select(NULL, &udpSetAnni, NULL, NULL, &timeoutonce))

{

// 接收缓冲区
char buffer[298];
memset(buffer, NULL, sizeof(buffer));
// 接收UDP包
recvfrom(nAnniSock, buffer, sizeof(buffer), NULL, (sockaddr*)&stSockCamera, &nLen);

}

}

// 所以只能设置为指定网卡的IP地址(据说设置无线网卡的IP地址也会失败)

你可能感兴趣的:(C++)