废话不多,上代码
1 WSADATA wsaData; 2 SOCKET sockRaw; 3 struct sockaddr_in from, host; 4 int fromlen = sizeof(from); 5 int packet_size = 0; 6 7 //版本号 8 if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0){ 9 fprintf(stderr,"WSAStartup failed: %d\n",GetLastError()); 10 ExitProcess(STATUS_FAILED); 11 } 12 13 //创建套接字 14 sockRaw = socket(AF_INET, SOCK_RAW, IPPROTO_IP); 15 if (sockRaw == INVALID_SOCKET) { 16 fprintf(stderr,"WSASocket() failed: %d\n",WSAGetLastError()); 17 ExitProcess(STATUS_FAILED); 18 } 19 20 //设置超时时间 21 int iret = 0; 22 char hostname[256]; 23 int timeout = 1000; 24 iret = setsockopt(sockRaw,SOL_SOCKET,SO_RCVTIMEO,(char*)&timeout, sizeof(timeout)); 25 if(iret == SOCKET_ERROR) { 26 fprintf(stderr,"failed to set send timeout: %d\n",WSAGetLastError()); 27 ExitProcess(STATUS_FAILED); 28 } 29 30 //设置IP头操作选项,其中flag设置为ture,亲自对IP头进行处理 31 //经验证、对比可得,这一步不必须,效果都是抓到的包含有IP头 32 int flag = 1; 33 iret = setsockopt(sockRaw, IPPROTO_IP, IP_HDRINCL, (char*)&flag, sizeof(flag)); 34 35 //把原始套接字绑定到本地网卡地址上 36 gethostname(hostname, sizeof(hostname)); 37 struct hostent* pHost = gethostbyname(hostname); 38 host.sin_addr = *(in_addr*)pHost->h_addr_list[0]; 39 host.sin_family = AF_INET; 40 host.sin_port = htons(57274); 41 iret = bind(sockRaw, (const sockaddr*)&host, sizeof(host)); 42 43 //设置SOCK_RAW 为SIO_RCVALL,以便接收所有的IP包(混杂模式) 44 DWORD dwValue = 1; 45 iret = ioctlsocket(sockRaw, SIO_RCVALL, &dwValue); 46 47 while (1) 48 { 49 iret = recv(sockRaw, buff, len, 0); 50 if (iret == SOCKET_ERROR) 51 { 52 continue; 53 } 54 55 //收到的数据被存到buff中,iret返回的是收到数据的长度 56 }
今天为这个搞了好长时间,最后发现是建立SOCKET的时候,将协议设成了IPPROTP_IPV4。
真心觉得这不算什么技术,不过是调用人家的函数而已。所以没心思往下,因为要做更重要的事。
但是还是把它记下来,算作一种积累吧
另外,在查资料的过程中,看到一个网页http://forums.codeguru.com/showthread.php?303112-How-to-capture-packet-using-winsock,大家可以去看看人家老外是怎么回答问题的。
真心佩服