我正在尝试捕获计算机上所有传输的数据包。我的代码在 Windows XP 中运行良好,但它只捕获 Windows 7 上的传出数据包并且看不到传入数据包。
这是代码的一个版本,它只计算接收到的数据包的大小(它看起来很大,但大部分只是定义)。此代码在 Windows XP 上正常工作,但在 Windows 7 上没有任何反应(卡在recvfrom
)(代码已完成,您可以在 Win7 上尝试):
#include <Winsock2.h>
#include <Mstcpip.h>
#include <iostream>
#include <string>
using namespace std;
#pragma comment(lib,"Ws2_32.lib")
struct SIP4HEADER
{
u_char ver_ihl; // Version (4 bits) + Internet header length (4 bits)
u_char tos; // Type of service
u_short tlen; // Total length
u_short ident; // Identification
u_short flags_fo; // Flags (3 bits) + Fragment offset (13 bits)
u_char ttl; // Time to live
u_char proto; // Protocol
u_short crc; // Header checksum
u_long saddr; // Source address
u_long daddr; // Destination address
u_int op_pad; // Option + Padding
};
// Error handling parts is removed for clarity
void main()
{
WSAData wsa={0};
WSAStartup(MAKEWORD(2,2),&wsa);
string strIPAddress;
cout << "Enter a local IP address to monitor: ";
cin >> strIPAddress;
SOCKET ListenSocket = socket(AF_INET, SOCK_RAW, IPPROTO_IP);
sockaddr_in sa_in;
sa_in.sin_family = AF_INET;
sa_in.sin_addr.s_addr = inet_addr( strIPAddress.c_str() ); //My local IP address
sa_in.sin_port = htons(0);
bind(ListenSocket,(SOCKADDR *) &sa_in, sizeof(sa_in));
int rcv=RCVALL_IPLEVEL;
DWORD b=0;
WSAIoctl(ListenSocket,SIO_RCVALL,&rcv,sizeof(rcv),0,0,&b,0,0);
char buf[2000];
SIP4HEADER* ih = (SIP4HEADER*)buf;
DWORD ReceivedKBytes = 0;
DWORD t = 0;
while( recvfrom(ListenSocket,buf,_countof(buf),0,NULL,NULL)!=-1 )
{
if(sa_in.sin_addr.s_addr == ih->daddr)
t += ntohs(ih->tlen) ;
// update each 20KB
if(t > 20*1024)
{
t=0;
ReceivedKBytes += 20;
cout << "Received KBs: " << ReceivedKBytes << endl;
}
}
}
唯一让我怀疑的是MSDN 上的这篇文章,他说:
不允许使用 IPPROTO_TCP 协议的原始套接字调用绑定函数
但我正在使用IPPROTO_IP
,并且绑定函数文档还说:
bind 函数也可用于绑定到原始套接字(套接字是通过调用类型参数设置为 SOCK_RAW 的套接字函数创建的)
所以看来这不是问题。尽管如此,我bind
在这段代码中调用和其他函数没有得到任何错误。我还省略bind
了导致recvfrom
错误10022 无效参数的调用函数。我也替换IPPROTO_IP
为,IPPROTO_TCP
但它也无济于事。
我不确定我是否做对了,但这段代码在 Windows XP 上没有任何问题。无论如何,我正在寻找一种在 Windows XP/7 上接收和发送与本地 IP 地址相关的数据包的方法。
还:
- 我在 Windows 7 的特权(管理员)模式下运行此代码。
- Winpcap 或其他第三方库对我来说不是可用的选项。