【问题标题】:Reading ICMP reply with select in Linux using C++使用 C++ 在 Linux 中通过 select 读取 ICMP 回复
【发布时间】:2012-12-30 02:40:09
【问题描述】:

我正在使用 C++ 和原始套接字向路由器发送 ICMP 请求,之后我想读取 ICMP 回复。我的问题是, select() 没有收到重播和超时。我没有收到任何错误(errno 正在返回成功)。路由器正在发送 ICMP 回复,因为我可以使用 Wireshark 看到回复。

http://i.imgur.com/0Wra1.png wireshark 截图

为了测试我的程序,我使用在 VirtualBox 4.2.6 上运行的 Ubuntu 12.10 和用于虚拟网络的 GN3。

我的源代码:

char buffer[IP_MAXPACKET]; // for the received ICMP reply
struct iphdr *ipRec; // ICMP header
timeval tv; // timeout
fd_set mySet; // descriptor set
...
tv.tv_sec = 3; // default time-out 3s
tv.tv_usec = 0;

int retval; // select
...
do {
        FD_ZERO(&mySet);
        FD_SET(mysocket, &mySet);

        retval = select(mysocket+1, &mySet, NULL, NULL, &tv);

        cout << "Errno after select:" << strerror(errno) << endl;

        if(retval == -1) {
            cerr << "select error" << endl;
            break;
        }
        else if (retval) {
            if((length = recvfrom(mysocket, buffer, MAX, 0, result->ai_addr, &(result->ai_addrlen))) == -1) {
                cerr << "Error: while receiving data." << endl;
            }
            else {
                cout << "good" << endl;

                ipRec = (struct iphdr*) buffer;
                icmpRec = (struct icmphdr*) (buffer + ipRec->ihl * 4);

                cout << "the packet." << " PID: " << ntohs(icmpRec->un.echo.id) << " Seq: " << ntohs(icmpRec->un.echo.sequence) << endl;

                if ((icmpRec->type == ICMP_ECHOREPLY) && (ntohs(icmpRec->un.echo.id) == pid) && (ntohs(icmpRec->un.echo.sequence) == (seq - 1))) {
                    minBuff = lengthBuff;
                }
            }
        } else {
            // getting here all the time = select times-out and reads no data

            cout << "mysocket:" << mysocket << endl;
            cout << "retval:" << retval << endl;
            maxBuff = lengthBuff;
            break;
        }
    } while (!((icmpRec->type == ICMP_ECHOREPLY) && (ntohs(icmpRec->un.echo.id) == pid) && (ntohs(icmpRec->un.echo.sequence) == (seq - 1))));

    if (packet)
        delete(packet);
    ...

感谢您的帮助。

【问题讨论】:

  • 注意
  • 是的,我的错,显然是 C++ :)
  • recvfrom 中的 MAX 是什么?那不应该是 IP_MAXPACKET 吗?
  • 修复了问题。在另一个线程中找到了解决方案:stackoverflow.com/questions/9688899/…。将 IPPROTO_RAW 更改为 IPPROTO_ICMP 修复了它。现在是选择读取 ICMP 回复数据包。
  • MAX 定义为 IP_MAXPACKET。

标签: c++ linux select icmp


【解决方案1】:

解决了这个问题。在另一个线程中找到了解决方案:ICMP packets are not being sent C。将 IPPROTO_RAW 更改为 IPPROTO_ICMP 修复了它。现在是选择读取ICMP回复包。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-26
    相关资源
    最近更新 更多