参考链接:

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. 数据库和linq中的 join(连接)操作

    sql中的连接 sql中的表连接有inner join,left join(left outer join),right join(right outer join),full join(full o ...

  2. [转]Android Volley完全解析(四),带你从源码的角度理解Volley

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17656437 经过前三篇文章的学习,Volley的用法我们已经掌握的差不多了,但是 ...

  3. Factorization Machines 学习笔记(三)回归和分类

      近期学习了一种叫做 Factorization Machines(简称 FM)的算法,它可对随意的实值向量进行预測.其主要长处包含: 1) 可用于高度稀疏数据场景:2) 具有线性的计算复杂度.本文 ...

  4. 常用分组函数count-avg-sum-max-min

    分组函数也称多行函数,用于对一组数据进行运算,针对一组数据(取自于多行记录的相同字段)只返回一个结果,例如计算公司全体员工的工资总和.最高工资.最低工资.各部门的员工平均工资(按部门分组)等.由于分组 ...

  5. springmvc入门详解

    首先,我们先写一个入门小案例,先熟悉一下springmvc是什么,了解一下springmvc的运行流程,对加强springmvc的深层理解有很大帮助 .第一步,创建一个maven项目: <?xm ...

  6. jquery之营销系统(补偿记录)

    var appPath = getAppPath(); $(function(){ $("#opreateHtml").window("close"); $(& ...

  7. C#多线程实践——线程同步

    下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程完成      ...

  8. poj3254状压DP入门

    G - 状压dp Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:65536KB     64bit ...

  9. PHPExcel用法有感

    今日项目需求导出excel.我用最简单的header头方式导出了,但是需求部门退回了,说不满足他们的需求,需要我按照他们的模板来导出. 然后想到了PHPExcel,没用过,走了不少弯路. 1.去官网下 ...

  10. nvm linux命令

    nvm alias default 0.12.10 nvm alias default 0.10.24 nvm list NVM_NODEJS_ORG_MIRROR=http://npm.taobao ...