关于recvfrom()的C语言Ping程序实现疑惑

Ping program implementation in C about recvfrom() doubts

我在网上找了很久。但是没有用。请帮助或尝试提供一些想法如何实现这一目标。

程序写完了,今天测试ping环回地址时,函数recvfrom()发送完包后,收到了“第一个”包(type 8),第二个recvfrom()收到了响应数据包(类型 0)。

后来发现奇数次的type值为8,偶数次的type值为0

我用Wireshark实际抓到的包每次都有对应的响应包,但是recvfrom()第一次收到的是出包

        // Send
        if (sendto(sockfd, &sendicmp, ICMP_SIZE, 0, (struct sockaddr *) &to, sizeof(to)) == -1) {
            printf("sendto() error \n");
            continue;
        }
        // Receive
        struct timeval timeout = {3, 0};//3s
        setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
        if ((n = recvfrom(sockfd, buf, BUF_SIZE, 0, (struct sockaddr *) &from, &fromlen)) < 0) {

            printf("Time out! \n");
            continue;
        }
        nreceived++;
        if (unpack(buf, n) == -1) {
            printf("unpack() error \n");
        }

enter image description here Since the type value is not 0, I let the output is not the ICMP packet sent to me

ICMP 类型 8 控制消息是回显请求。类型 0 是回显回复。因此,听起来您的程序除了收到对这些请求的答复外,还收到了自己的请求。如果您成功 ping 回环地址,那是很自然的,因为这就是环回的工作方式。

对于 TCP 和 UDP 来说问题不大,因为这些协议提供了在普通 IP 之上的端口概念,以区分通过同一地址进行通信的不同应用程序。 ICMP 没有,因此接收 ICMP 消息的进程有责任执行自己的消息过滤。特别是 ping 程序可能会忽略传入的 ICMP 消息,而不是 echo 回复(类型 0)。它还可能使用 ICMP 的后四个八位字节 header 来区分对其自身回显请求的答复与同时对其他程序的答复 运行。