ping功能实现(ICMP)

来源:互联网 发布:淘宝的穿衣助手在哪 编辑:程序博客网 时间:2024/05/22 11:44

简单记录下项目中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;}

 
原创粉丝点击