使用原始套接字:SOCK_RAW
需要ICMP
代码如下:
- #include<iostream>
- #include<WinSock2.h>
- using namespace std;
- #pragma comment(lib, "WS2_32.lib")
- typedef struct icmp_hdr{
- unsigned char icmp_type;
- unsigned char icmp_code;
- unsigned short icmp_checksum;
- unsigned short icmp_id;
- unsigned short icmp_sequence;
- unsigned long icmp_timnestamp;
- }ICMP_HDR, *PICMP_HDR;
- typedef struct _IPHeader{
- UCHAR iphVerLen;
- UCHAR ipTOS;
- USHORT ipLength;
- USHORT ipID;
- USHORT ipFlags;
- UCHAR ipTTL;
- UCHAR ipProtocol;
- USHORT ipChecksum;
- ULONG ipSource;
- ULONG ipDestination;
- }IPHeader, *PIPHeader;
- USHORT checksum(USHORT* buffer, int size)
- {
- unsigned long cksum = 0;
- while(size > 1)
- {
- cksum += *buffer++;
- size -= sizeof(USHORT);
- }
- // 奇数,将最后一个字节扩展到双字, 再累加
- if(size)
- cksum += *(UCHAR*)buffer;
- //高16 低16相加,取反
- cksum = (cksum >> 16) + (cksum & 0xffff);
- cksum += (cksum >> 16);
- return (USHORT)(~cksum);
- }
- int main(void)
- {
- char szDestIp[] = "127.0.0.1";
- SOCKET sRaw= ::socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
- //SetTimeout(sRaw, 1000, TRUE);
- SOCKADDR_IN dest;
- dest.sin_family = AF_INET;
- dest.sin_port = htons(5674);
- dest.sin_addr.S_un.S_addr = inet_addr(szDestIp);
- char buff[sizeof(ICMP_HDR) + 32];
- ICMP_HDR *pIcmp = (ICMP_HDR*)buff;
- pIcmp->icmp_type = 8;
- pIcmp->icmp_code = 0;
- pIcmp->icmp_id = (USHORT)::GetCurrentProcess();
- pIcmp->icmp_checksum = 0;
- pIcmp->icmp_sequence = 0;
- memset(&buff[sizeof(ICMP_HDR)], 'E', 32);
- //发送
- USHORT nSeq = 0;
- char recvBuf[1024];
- SOCKADDR_IN from;
- int nLen = sizeof(from);
- while(TRUE)
- {
- static int nCount = 0;
- int nRet;
- if(nCount++ == 4)
- break;
- pIcmp->icmp_checksum = 0;
- pIcmp->icmp_timnestamp = ::GetTickCount();
- pIcmp->icmp_sequence = nSeq++;
- pIcmp->icmp_checksum = checksum((USHORT*)buff, sizeof(ICMP_HDR) + 32);
- nRet = ::sendto(sRaw, buff, sizeof(ICMP_HDR) + 32, 0, (SOCKADDR*)&dest, sizeof(dest));
- if(nRet == SOCKET_ERROR)
- {
- cout << "sendto error:" << ::WSAGetLastError() << endl;
- return -1;
- }
- nRet = ::recvfrom(sRaw, recvBuf, 1024, 0, (sockaddr*)&from, &nLen);
- if(nRet == SOCKET_ERROR)
- {
- if(::WSAGetLastError() == WSAETIMEDOUT)
- {
- cout << "time out" << endl;
- continue;
- }
- cout << "recvfrom failed:" << ::WSAGetLastError() << endl;
- return -1;
- }
- //解析
- int nTick = ::GetTickCount();
- if(nRet < sizeof(IPHeader) + sizeof(ICMP_HDR))
- {
- cout << "Too few bytes from " << ::inet_ntoa(from.sin_addr) << endl;
- }
- ICMP_HDR *pRecvIcmp = (ICMP_HDR*)(recvBuf + sizeof(IPHeader));
- if(pRecvIcmp->icmp_type != 0)
- {
- cout << "nonecho type " << pRecvIcmp->icmp_type << " recvd" << endl;
- return -1;
- }
- if(pRecvIcmp->icmp_id != ::GetCurrentProcessId())
- {
- cout << "someone ele's packet!" << endl;
- return -1;
- }
- cout << nRet << " bytes from " << inet_ntoa(from.sin_addr) ;
- cout << "icmp_seq = " << pRecvIcmp->icmp_sequence ;
- cout << "time: " << nTick - pRecvIcmp->icmp_timnestamp << " ms";
- cout << endl;
- Sleep(1000);
- }
- return 0;
- }
jofranks 13.7.24 于南昌
版权声明:本文为博主原创文章,未经博主允许不得转载。