简单记录下项目中ping功能实现

笔记:ping功能实现

void Handler::handlePingDepot(const char *ip)
{
int mSize=50*1024; bzero(&mDestAddr,sizeof(mDestAddr));
mDestAddr.sin_family = AF_INET;
mDestAddr.sin_addr.s_addr = inet_addr(ip);
if( (mSockFd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP)) < 0){
LogE("socket error\n");
return;
}
::setsockopt(mSockFd,SOL_SOCKET,SO_RCVBUF,&mSize,sizeof(mSize) );
mPid=getpid();
recvICMPPacket();
} void Handler::sendICMPPacket()
{
int mPacketSize = 0;
mSend++;
int n;
mPacketSize = setICMPHander(mSend);
if((n = ::sendto(mSockFd, mSendPacket,mPacketSize, 0,(struct sockaddr *)&mDestAddr, sizeof(mDestAddr))) < 0){
LogE("send icmp packet error\n");
return;
}
} int Handler::setICMPHander(int mSeq)
{
int mPackSize;
struct icmp *icmp; icmp = (struct icmp*)mSendPacket;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_seq = mSeq;
icmp->icmp_id = mPid;
mPackSize = 8 + dataLen;
icmp->icmp_cksum = calCheckSum( (unsigned short *)icmp,mPackSize);
return mPackSize;
}
void Handler::recvICMPPacket()
{
int n;
mPingTag = true;
socklen_t mFromLen;
int mMaxFds = 0;
fd_set mReadFds;
struct timeval mTimeout;
mFromLen = sizeof(struct sockaddr_in);
while(1){ sendICMPPacket();
mTimeout.tv_sec = mConfig->mSCUTimeout;
mTimeout.tv_usec = 0;
FD_ZERO(&mReadFds);
FD_SET(mSockFd,&mReadFds);
mMaxFds = mSockFd + 1;
n = select(mMaxFds, &mReadFds, NULL, NULL, &mTimeout);
if(n <= 0 ){
LogE("ping %s icmp packet error\n",inet_ntoa(mDestAddr.sin_addr));
mPingTag = false;
break;
}else{
memset(mRecvPacket, 0, sizeof(mRecvPacket));
if((n = ::recvfrom(mSockFd, mRecvPacket, sizeof(mRecvPacket), 0, (struct sockaddr *)&mFrom, &mFromLen)) < 0){
LogE("recv icmp packet error\n");
return;
}
if(parseICMPPacket(mRecvPacket, n) == true){
mIPCall->sendDepotMsg(mFlag);
mRecvPandown = true;
mSend = 0;
break;
}
}
}
} bool Handler::parseICMPPacket(char *buf, int len)
{
int mIpHdrLen;
struct ip *mIP;
struct icmp *mICMP; mIP = (struct ip *)buf;
mIpHdrLen = mIP->ip_hl << 2; mICMP = (struct icmp *)(buf + mIpHdrLen);
len -= mIpHdrLen;
if( len < 8){
LogE("ICMP packets's length is less than 8\n");
return false;
}
if( (mICMP->icmp_type == ICMP_ECHOREPLY) && (mICMP->icmp_id == mPid) ) {
LogE("%d byte from %s: icmp_seq=%u ttl=%d sucess\n",
len,
inet_ntoa(mFrom.sin_addr),
mICMP->icmp_seq,
mIP->ip_ttl);
return true;
}else{
return false;
}
}
unsigned short Handler::calCheckSum(unsigned short *addr,int len)
{
int mLeft = len;
int sum=0;
unsigned short *w = addr;
unsigned short answer = 0;
while(mLeft > 1){
sum += *w++;
mLeft -= 2;
}
if( mLeft == 1){
*(unsigned char *)(&answer) = *(unsigned char *)w;
sum += answer;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
answer =~ sum;
return answer;
}
												

ping功能实现(ICMP)的更多相关文章

  1. Linux下实现ping功能

    实现ping功能,就肯定要用到ping命令,那么在Linux下ping命令为: ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面&g ...

  2. Java实现ping功能的三种方法及Linux的区分

    前大半部份转自:https://blog.csdn.net/futudeniaodan/article/details/52317650 检测设备的运行状态,有的是使用ping的方式来检测的.所以需要 ...

  3. 你知道PING功能是怎么实现的吗

    以太网的协议有层,而每层都包含有更多的协议.所谓协议,通俗的讲就是通信双方约定的规则. 今天我们介绍一些一个听起来陌生却有很常用的协议,ICMP协议. —ICMP是(Internet Control ...

  4. 如何开放 Azure 虚拟机 Ping 功能

    前言 文章<使用 PsPing & PaPing 进行 TCP 端口连通性测试>中提到,ICMP 协议的数据包无法通过 Azure 的防火墙和负载均衡器,所以不能直接使用 Ping ...

  5. 【虚拟机-网络IP】如何开放 Azure 虚拟机 Ping 功能

    前言 文章<使用 PsPing & PaPing 进行 TCP 端口连通性测试>中提到,ICMP 协议的数据包无法通过 Azure 的防火墙和负载均衡器,所以不能直接使用 Ping ...

  6. ping 原理与ICMP协议[转]

    原文:http://blog.csdn.net/inject2006/article/details/2139149 ping 的原理     ping 程序是用来探测主机到主机之间是否可通信,如果不 ...

  7. ping 原理与ICMP协议

    ping 的原理     ping 程序是用来探测主机到主机之间是否可通信,如果不能ping到某台主机,表明不能和这台主机建立连接.ping 使用的是ICMP协议,它发送icmp回送请求消息给目的主机 ...

  8. VB6之ICMP实现ping功能

    代码备忘 'code by lichmama from cnblogs.com Private Type IPAddr ip1 As Byte ip2 As Byte ip3 As Byte ip4 ...

  9. C++实现ping功能

    今天接到需求要实现ping的功能,然后网上查了一些资料,对网络编程的一些函数熟悉了一下,虽然还有一些细节不清楚,但是慢慢积累. 要实现这样的功能: 基础知识 ping的过程是向目的IP发送一个type ...

  10. C++实现ping功能<转>

    今天接到需求要实现ping的功能,然后网上查了一些资料,对网络编程的一些函数熟悉了一下,虽然还有一些细节不清楚,但是慢慢积累. 要实现这样的功能: 基础知识 ping的过程是向目的IP发送一个type ...

随机推荐

  1. 优先使用C++的别名声明(using)来替换typedef

    C++98中,我们如果想用简写的方式表达一个类型,那么可以使用typedef关键字: typedef std::unique_ptr<std::unordered_map<std::str ...

  2. 论zzy的苏州话

    乘地铁(ceng) - 盛饭(seng) 无法无天 - 12345 掀被子 - 先干嘛,再干嘛 ?待更新

  3. Unity泛型单例模式

    using System.Collections; using System.Collections.Generic; using UnityEngine; public class Singleto ...

  4. 什么是5G垂直行业?

    什么是垂直行业呢? 感觉"垂直行业"这个词在太多地方遇到,但是这个词的涵盖范围到底是什么呢? 垂直这一概念源于两条直线(或平面)的直角交叉,两条直线是相互作为参照物的.比如,我们可 ...

  5. c++中文编码格式

    c++程序中涉及到中文字符的输入输出以及其他操作经常会出现乱码.乱码主要是由于程序的源文件编码.可执行文件编码以及程序运行环境的编码不匹配导致.比如,c++源程序文件编码为GB18030, 在源程序中 ...

  6. python内置函数range()—对象创建函数

    range()函数 介绍 range()函数实际上表示一个不可变的数字序列类型,通常用于在for循环中指定特定的次数. range()的格式: range(stop) range(start, sto ...

  7. VsCode里面运行mvn命令显示The JAVA_HOME environment variable is not defined correctly

    问题描述 关于这个问题,就是环境配置出了问题!!! 问题解决 在settings.json里面,配置的环境的路径不能出错,我就是在配置的时候,名为Environments的文件夹写成Environme ...

  8. git clone的时候出现 fatal: unable to access 'https://github.com/...':OpenSSL SSL_read: Connection was reset, errno 10054解决方法

    git clone的时候出现fatal: unable to access 'https://github.com/...':OpenSSL SSL_read: Connection was rese ...

  9. 做bad apple第一步:超级好用的you-get下载各大网站音频!!!!

    1 安装在cmd中输入pip3 install you-get 就行了 2 简单用法下载视频: 超级暴力,直接 you-get + "网站" 就没了,会下载到当前路径.我想下载到哪 ...

  10. 使用cmd命令行安装 windows系统

    条件:Microsoft WindowsPE 或其他第三方 WindowsPE 1. 使用 diskpart 分区: list disk:列出所有磁盘 select disk  编号:选择某块磁盘 c ...