参考链接:

http://blog.csdn.net/zpxili/article/details/11542041

http://blog.csdn.net/cbuttonst/article/details/7610801

上面两位兄弟的是发一个icmp包,就收一次。在我的电脑上运行的时候,

估计是我的网络中有回环,结果每次收到的都是刚刚发出去的icmp包,

用wireshark抓包又能够抓到正确的reply包。调试了好久,修改如下。

//CPing.h

#ifndef CPING_HJ
#define CPING_HJ
#include <WinSock2.h>
#include <string>
typedef struct _SICMPHDR //icmp
{
unsigned char icmp_type;
unsigned char icmp_code;
unsigned short icmp_checksum;
unsigned short icmp_id;
unsigned short icmp_sequence;
unsigned long icmp_timestamp;
} ICMPHDR, *PICMPHDR;
typedef struct _SIPHDR //ip
{
UCHAR ip_hVerLen;
UCHAR ip_TOS;
USHORT ip_Length;
USHORT ip_ID;
USHORT ip_Flags;
UCHAR ip_TTL;
UCHAR ip_Protacol;
USHORT ip_Checksum;
ULONG ip_Source;
ULONG ip_Destination;
} IPHDR;
class CPing
{
public:
CPing();
~CPing();
void m_vPing();
private:
bool m_bSendData(char* pcBuf,int nBufLen,sockaddr_in* pstAddr);
bool m_bRecvData(char* pcBuf,int iBufLen,sockaddr_in* pstRecvAddr,int &riRecvLen);
void m_vInitICMP(PICMPHDR pstICMPHDR,int nSequence);
u_short m_usCheckSum(unsigned short *pusBuf,int iLen);
SOCKET m_iSocket;
};
#endif

//CPing.cpp

#include "CPing.h"
#include <stdio.h>
#define DATA_SIZE 32
#define RECV_SIZE 1024
const int SEND_PACKAGE_SIZE = 30;
const int MAX_TIME = 3000; //ms
CPing::CPing()
{
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2,2);
int nRet = WSAStartup(wVersion,&wsaData);
if( nRet != 0 )
{
printf("WSAStartup failed with error: %d\n", nRet);
return;
}
if( LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2 )
{
printf("Could not find a usable version of Winsock.dll\n");
WSACleanup();
return;
}
m_iSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if( m_iSocket == INVALID_SOCKET )
{
printf("Socket err\n");
WSACleanup();
return;
}
}
CPing::~CPing()
{
if( INVALID_SOCKET != m_iSocket )
{
closesocket(m_iSocket);
}
WSACleanup();
}
void
CPing::m_vPing()
{
char acName[] = "www.vidagrid.com";
hostent *pstHost = gethostbyname(acName);
if( pstHost == NULL )
{
printf("CPing::m_vPing() gethostbyname err\n");
return;
}
sockaddr_in stDesAddr;
stDesAddr.sin_family = AF_INET;
stDesAddr.sin_port = htons(0);
stDesAddr.sin_addr = *((struct in_addr *)(pstHost->h_addr));
//stDesAddr.sin_addr.s_addr = inet_addr("172.17.92.110");
char acIPAddr[23] = {0};
strcpy(acIPAddr, inet_ntoa(stDesAddr.sin_addr));
printf("CPing::m_vPing() acIPAddr: %s\n", acIPAddr);
int iSendBufLen = sizeof(ICMPHDR) + DATA_SIZE;
char* pcIcmp = new char[iSendBufLen];
memset(pcIcmp, 0, iSendBufLen);
PICMPHDR pstIcmp = (PICMPHDR)pcIcmp;
int iSequence = 0;
int iCount = SEND_PACKAGE_SIZE;
while ( iCount-- > 0 )
{
m_vInitICMP(pstIcmp, iSequence++);
pstIcmp->icmp_checksum = m_usCheckSum((unsigned short*)pstIcmp,sizeof(ICMPHDR) + DATA_SIZE); //校验值
m_bSendData((char*)pstIcmp, iSendBufLen, &stDesAddr);
}
int iMinimum = 0;
int iMaximum = 0;
int iSumTime = 0;
iCount = 0;
DWORD dwStartTime = GetTickCount();
printf("\nPinging %s [%s] with 32 bytes of data:\n\n", acName, acIPAddr);
while( (GetTickCount()-dwStartTime) <= MAX_TIME)
{
sockaddr_in stRcvAddr;
char acBuf[RECV_SIZE] = {0};
int iRecvLen = 0;
m_bRecvData(acBuf, sizeof(acBuf), &stRcvAddr, iRecvLen);
int iHeadLen = sizeof(IPHDR) + sizeof(ICMPHDR) + DATA_SIZE;
if( iRecvLen < iHeadLen )
{
printf("CPing::m_vPing() tool few data~\n\n");
continue;
}
IPHDR *ipHead = (IPHDR *)acBuf;
PICMPHDR icmpRecv = (PICMPHDR) (acBuf + sizeof(IPHDR) );
if( icmpRecv->icmp_type != 0 )
{
printf("CPing::m_vPing() Icmp Type err~, 0x%x\n\n", icmpRecv->icmp_type);
continue;
}
if( icmpRecv->icmp_id != GetCurrentProcessId() )
{
printf("CPing::m_vPing() Icmp ID err~\n\n");
continue;
}
int iCurUsedTime = GetTickCount() - icmpRecv->icmp_timestamp;
printf("Reply from %s: bytes=%d time=%ums TTL=%d\n",
inet_ntoa(stRcvAddr.sin_addr),
DATA_SIZE,
iCurUsedTime,
ipHead->ip_TTL);
iSumTime += iCurUsedTime;
if(iCount != 0)
{
if(iCurUsedTime<iMinimum) iMinimum = iCurUsedTime;
else if(iCurUsedTime>iMaximum) iMaximum = iCurUsedTime;
}
else
{
iMinimum = iCurUsedTime;
iMaximum = iCurUsedTime;
}
iCount++;
}
//show statistics
printf("\nPing statistics for %s:\n", acIPAddr);
printf("\tPackets: Sent = %d, Received = %d, Lost = %d (%.2lf%% loss),\n",
SEND_PACKAGE_SIZE, iCount, SEND_PACKAGE_SIZE-iCount, ((double)(SEND_PACKAGE_SIZE-iCount))/SEND_PACKAGE_SIZE*100 );
printf("Approximate round trip times in milli-seconds:\n");
printf("\tMinimum = %dms, Maximum = %dms, Average = %dms\n",
iMinimum, iMaximum, iSumTime/iCount);
delete pcIcmp;
getchar();
}
bool
CPing::m_bSendData(char* pcBuf,int iBufLen,sockaddr_in* pstAddr)
{
printf("CPing::m_bSendData() \n");
if( pstAddr == NULL )
{
printf("CPing::m_bSendData() pstAddr == NULL\n");
return false;
}
int iTimeout = 1000;
int iRet = setsockopt(m_iSocket, SOL_SOCKET, SO_SNDTIMEO, (char*)&iTimeout, sizeof(int));
if( iRet == SOCKET_ERROR )
{
printf("CPing::m_bSendData() setsockopt SO_SNDTIMEO err\n");
return false;
}
iRet = sendto(m_iSocket, pcBuf, iBufLen, 0, (sockaddr*)pstAddr, sizeof(sockaddr));
if( iRet == SOCKET_ERROR )
{
if (WSAETIMEDOUT == WSAGetLastError())
{
printf("CPing::m_bSendData() timeout err\n");
return false;
}
else
{
printf("CPing::m_bSendData() sendto err\n");
return false;
}
}
return true;
}
bool
CPing::m_bRecvData(char* pcBuf,int iBufLen,sockaddr_in* pstRecvAddr,int &riRecvLen)
{
printf("CPing::m_bRecvData() \n");
if( INVALID_SOCKET == m_iSocket )
{
printf("CPing::m_bRecvData() INVALID_SOCKET\n");
return false;
}
int iTimeout = 1000;
int iRet = setsockopt(m_iSocket, SOL_SOCKET, SO_RCVTIMEO , (char*)&iTimeout, sizeof(int));
if( SOCKET_ERROR == iRet )
{
printf("CPing::m_bRecvData() setsockopt SO_RCVTIMEO error\n");
return false;
}
int nAddrLen = sizeof(sockaddr);
iRet = recvfrom(m_iSocket, pcBuf, iBufLen, 0, (sockaddr*)pstRecvAddr, &nAddrLen);
if( SOCKET_ERROR == iRet )
{
if (WSAETIMEDOUT == WSAGetLastError())
{
printf("CPing::m_bRecvData() timeout err\n");
return false;
}
else
{
printf("CPing::m_bRecvData() recvfrom err\n");
return false;
}
}
riRecvLen = iRet;
return true;
}
void
CPing::m_vInitICMP(PICMPHDR pstICMPHDR,int iSequence)
{
if( pstICMPHDR == NULL )
return;
pstICMPHDR->icmp_type = 8; //request
pstICMPHDR->icmp_code = 0; //icmp request
pstICMPHDR->icmp_sequence = iSequence;
pstICMPHDR->icmp_id = (unsigned short)GetCurrentProcessId();
pstICMPHDR->icmp_timestamp = GetTickCount();
pstICMPHDR->icmp_checksum = 0; //校验值
}
unsigned short
CPing::m_usCheckSum(unsigned short *pusBuf,int iLen)
{
USHORT cksum=0;
while(iLen>1)
{
cksum+=*pusBuf++;
iLen-=sizeof(USHORT);
}
if(iLen)
{
cksum+=*pusBuf++;
}
cksum=(cksum>>16)+(cksum&0xffff);
cksum+=(cksum>>16);
return (USHORT)(~cksum);
}

//main.cpp

#include "CPing.h"
#include <stdio.h>
#include <winsock2.h>
#include <iostream>
#include <windows.h>
using namespace std;
#pragma comment(lib, "ws2_32.lib")
int main()
{
CPing oPing;
oPing.m_vPing();
return 0;
}

当icmp_type8时,这是一个请求包(ECHO包)。

当icmp_type0时,这是一个响应消息报(ECHO REPLY包),就是对请求包的回应。

socket 发送Ping包的更多相关文章

  1. python socket发送魔法包网络唤醒开机.py

    python socket发送魔法包网络唤醒开机.py 现在的电脑应该都普遍支持有线网络的WOL了,支持无线网络唤醒的电脑,可能比较少. """ python socke ...

  2. 【网络编程2】网络编程基础-发送ICMP包(Ping程序)

    IP协议 网络地址和主机协议 位于网络层的协议,主要目的是使得网络能够互相通信,该协议使用逻辑地址跨网络通信,目前有两个版本IPV4,IPV6. 在IPV4协议中IP地址是一个32位的数备,采用点分四 ...

  3. C# TCP socket发送大数据包时,接收端和发送端数据不一致 服务端接收Receive不完全

    简单的c# TCP通讯(TcpListener) C# 的TCP Socket (同步方式) C# 的TCP Socket (异步方式) C# 的tcp Socket设置自定义超时时间 C# TCP ...

  4. c++如何使用SOCKET 发送HTTP1.1 GET POST请求包

    如何使用SOCKET 发送HTTP1.1 GET POST请求包 分类: 无线通信 C/C++2009-10-29 10:58 14259人阅读 评论(15) 收藏 举报 socket服务器actio ...

  5. loadrunner使用socket协议来实现客户端对服务器产生压力实例。(通过发送心跳包,达到连接多个客户端的目的)

    #include "lrs.h" vuser_init(){ char *ip; int handler; //编写获取LR分配的Vuser IP函数,将IP保存在ip变量中. i ...

  6. python网络编程-socket发送大数据包问题

    一:什么是socket大数据包发送问题 socket服务器端或者客户端在向对方发送的数据大于对方接受的缓存时,会出现第二次接受还接到上次命令发送的结果.这就出现象第一次接受结果不全,第二次接果出现第一 ...

  7. sendto频率过快导致发送丢包

    编写一个转发模块,虽然没有要求一转多时要达到多少路(不采用组播的情况下,单纯的一路转成多路),但是本着物尽其用的原则,尽可能测试一下极限. 网络环境:1000M,直连,多网卡 系统:Linux ver ...

  8. android firmware 利用UDP socket发送Magic Packet--c语言版本

    android firmware 利用UDP socket发送Magic Packet 1 Magic Packet格式: 6个0xFF + 16个Dst Mac Address 2 代码需要设置目的 ...

  9. socket的半包,粘包与分包的问题

    http://zhaohuiopensource.iteye.com/blog/1541270 首先看两个概念: 短连接: 连接->传输数据->关闭连接    HTTP是无状态的,浏览器和 ...

随机推荐

  1. Android开发之发送短信

    本实例通过SmsManager的sendTextMessage方法实现发送短信关于SmsManager的具体解释大家能够參照:Android开发之SmsManager具体解释 实例执行效果图: 程序代 ...

  2. struts2操作数据库

    struts2操作数据库是刚開始学习的人的一个难点也是一个重点,如今我为大家解说一下struts2操作数据库,使用struts2对数据库进行增.删.改.查和分页查询,请看以下的代码: User类 pu ...

  3. Verilog之i2c合约

    说明:i2c乔布斯.有这么多的事情在网上参考. 时刻:2014年5一个月6周二星期 1.问题叙述性说明: 正如图.已知的时钟clk为100k,rst为复位信号.上升沿有效,基于Verilog HDL或 ...

  4. web开发小白之路

    今天就来谈谈本人从事web开发的一系列白只又白的经历,本人刚开始是从事ios开发的,由于一系列的变故现在变为了web前端开发,不过说来也奇怪,刚开始接触前端时间可以说是彻底蒙圈,各种选择器,各种适配搞 ...

  5. Pythn中的super用法

    在Python类的方法(method)中,要调用父类的某个方法,在Python 2.2以前,通常的写法如代码段1: 代码段1: 代码如下: class A: def __init__(self): p ...

  6. Solr集成IK中文分词器

    1.将IKAnalyzer-2012-4x.jar拷贝到example\solr-webapp\webapp\WEB-INF\lib下: 2.在schema.xml文件中添加fieldType: &l ...

  7. python 下的数据结构与算法---2:大O符号与常用算法和数据结构的复杂度速查表

    目录: 一:大O记法 二:各函数高阶比较 三:常用算法和数据结构的复杂度速查表 四:常见的logn是怎么来的 一:大O记法 算法复杂度记法有很多种,其中最常用的就是Big O notation(大O记 ...

  8. CSS背景特殊属性值

    CSS代码示例-背景附着属性(background-attachment)-[背景图固定不动,不跟随滚动条滚动]:<html><head><title>背景附着属性 ...

  9. Polyline对象 - (及其他对象的关系)

    Polyline对象是由一个或多个相连或者不相连的path对象的有序集合,通常用来代表线状地物如道路,河流,管线等等.

  10. .NET中常见的内存泄露问题——GC、委托事件和弱引用

    一.什么是内存泄露(memory leak)? 内存泄露不是指内存坏了,也不是指内存没插稳漏出来了,简单来说,内存泄露就是在你期待的时间内你程序所占用的内存没有按照你想象中的那样被释放. 因此什么是你 ...