简单记录下项目中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. NRF52832的FDS程序,参考非蓝牙例程修改而来(需要增加DFU的基础上只要增加如下程序即可解决)

    /* Dummy configuration data. */ static configuration_t m_dummy_cfg = { .config1_on = false, .config2 ...

  2. 安装Win11需要网络才能下一步怎么跳过

    1.先Shift+F10打开命令提示符 2.运行C:\Windows\System32\oobe\BypassNRO.cmd 3.自动重启来到联网这一步,多了一个没有网络的选项,进入.

  3. java8 stream按某个字段分组,允许分组字段是null

    Map<String, List<Dto>> deviceMap = deviceList.stream().collect(Collectors.groupingBy(Dto ...

  4. Oracle coalesce函数 用于选取不为空的字段值

    coalesce(A,B)  若A为空则值为B 主流数据库系统都支持COALESCE()函数,这个函数主要用来进行空值处理,其参数格式如下: COALESCE ( expression,value1, ...

  5. FCARM - Output Name not specified, please check 'Options for Target - Utilit问题

    FCARM - Output Name not specified, please check 'Options for Target - Utilit问题 按照书上说明按步操作,但是书上是按照kei ...

  6. Less1-union select 联合查询注入

    在学习之前,我们要知道,什么是 SQL 注入? 一句话来说,攻击者通过注入恶意的SQL命令,破坏SQL查询语句的结构,从而达到执行恶意SQL语句的目的. SQL注入漏洞的危害是很大的,常常会导致整个数 ...

  7. badapple最后一步,讲黑白图转为字符图,然后输出就行了。

    from PIL import Image import os char_s = list(" .,-'`:!1+*abcdefghijklmnopqrstuvwxyz<>()\ ...

  8. 数据库中1NF,2NF,3NF的判别

    参照:https://blog.csdn.net/qq_28888837/article/details/98733448 1NF:每一个都是最原子化.  2NF:找到主键后,每一个非主键对主键都是完 ...

  9. 除select外查询数据的另一种姿势

    1.24 1.[GYCTF2020]Blacklist buuctf上的题目 1.解题过程 输入1会返回一个数组,加上单引号就报错了,说明存在注入 以前做过类似的估计是堆叠注入,尝试一下 注入成功 正 ...

  10. P8112 符文破译

    题目描述 将字符串 \(T\) 拆成若干个子串,使这些子串为字符串 \(S\) 的前缀,要求拆分形成的子串数最小. 思路整理 实际上并不需要倒着枚举,也不需要线段树,更不需要 Z 函数. 如果你做过 ...