我用C++、icmp制作了Ping程序。但在安卓上不行

问题描述 投票:0回答:1

这是 ping 代码。在

select
函数之后,retval 只是 0。我检查了这在 mac os 上运行良好。我查了很多ip。但它不仅仅适用于 Android 设备。我不知道有什么问题。我第一次使用 SOCK_RAW 制作套接字,但它仅适用于超级用户。所以我把它改成SOCK_DGRAM。它适用于普通用户的 mac 操作系统。跟这个有关系吗

int ping(string target)
    {
        int s, i, cc, packlen, datalen = DEFDATALEN;
        struct hostent *hp;
        struct sockaddr_in to, from;
        struct ip *ip;
        u_char *packet, outpack[MAXPACKET];
        char hnamebuf[MAXHOSTNAMELEN];
        string hostname;
        struct icmp *icp;
        int ret, fromlen, hlen;
        fd_set rfds;
        struct timeval tv;
        int retval;
        struct timeval start, end;
        int end_t;
        bool cont = true;

        to.sin_family = AF_INET;
        to.sin_addr.s_addr = htonl(inet_addr(target.c_str()));
        //to.sin_port = 0;

        if (to.sin_addr.s_addr != (u_int)-1)
        {
            hostname = target;
            pErrorLabel->setString(hostname);
        }
        else
        {
            hp = gethostbyname(target.c_str());

            if (!hp)
            {
                pErrorLabel->setString("Unknown host");
                cerr << "unknown host " << target << endl;

                return -1;
            }

            to.sin_family = hp->h_addrtype;
            bcopy(hp->h_addr, (caddr_t)&to.sin_addr, hp->h_length);
            strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
            hostname = hnamebuf;
        }

        packlen = datalen + MAXIPLEN + MAXICMPLEN;

        if ((packet = (u_char *)malloc((u_int)packlen)) == NULL)
        {
            pErrorLabel->setString("malloc error");
            cerr << "malloc error\n";
            return -1;
        }


        if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0)
        {
            pErrorLabel->setString("administrator");
            return -1; /* Needs to run as superuser!! */
        }

        icp = (struct icmp *)outpack;
        icp->icmp_type = ICMP_ECHO;
        icp->icmp_code = 0;
        icp->icmp_cksum = 0;
        icp->icmp_seq = 12345;
        icp->icmp_id = getpid();

        cc = datalen + ICMP_MINLEN;
        icp->icmp_cksum = in_cksum((unsigned short *)icp, cc);

        gettimeofday(&start, NULL);

        i = sendto(s, (char *)outpack, cc, 0, (struct sockaddr*)&to, (socklen_t)sizeof(struct sockaddr_in));

        if (i < 0 || i != cc)
        {
            if (i < 0)
                perror("sendto error");
            cout << "wrote " << hostname << " " << cc << " chars, ret= " << i << endl;
        }

        FD_ZERO(&rfds);
        FD_SET(s, &rfds);
        tv.tv_sec = 5;
        tv.tv_usec = 0;

        std::stringstream ss;
        ss << "socket=" << (int)s;
        pErrorLabel->setString(ss.str().c_str());

        while (cont)
        {
            retval = select(s + 1, &rfds, NULL, NULL, &tv);

            if (retval == -1)
            {
                perror("select()");
                pErrorLabel->setString("select()");
                return -1;
            }
            else if (retval)
            {
                fromlen = sizeof(sockaddr_in);

                if ((ret = recvfrom(s, (char *)packet, packlen, 0, (struct sockaddr *)&from, (socklen_t*)&fromlen)) < 0)
                {
                    perror("recvfrom error");
                    pErrorLabel->setString("recvfrom error");
                    return -1;
                }

                // Check the IP header
                ip = (struct ip *)((char*)packet);
                hlen = sizeof(struct ip);

                if (ret < (hlen + ICMP_MINLEN))
                {
                    cerr << "packet too short (" << ret << " bytes) from " << hostname << endl;;

                    return -1;
                }

                // Now the ICMP part 
                icp = (struct icmp *)(packet + hlen);

                if (icp->icmp_type == ICMP_ECHOREPLY)
                {
                    if (icp->icmp_seq != 12345)
                    {
                        cout << "received sequence # " << icp->icmp_seq << endl;
                        continue;
                    }

                    if (icp->icmp_id != getpid())
                    {
                        cout << "received id " << icp->icmp_id << endl;

                        continue;
                    }

                    cont = false;
                }
                else
                {


                    continue;
                }

                gettimeofday(&end, NULL);

                end_t = 1000000 * (end.tv_sec - start.tv_sec) + (end.tv_usec - start.tv_usec);

                if (end_t < 1)
                    end_t = 1;

                cout << "Elapsed time = " << end_t << " usec" << endl;

                return end_t;
            }
            else
            {
                cout << "No data within one seconds.\n";

                return 0;
            }
        }

        return 0;
    }
android c++ icmp
1个回答
0
投票

在 Android 上,您无法从非原始套接字读取 ip 标头,因此只需直接获取 icmp 标头即可:

icp = (struct icmp *)(数据包);

© www.soinside.com 2019 - 2024. All rights reserved.