【问题标题】:Send an UDP packet and receive an ICMP response from router in C发送UDP数据包并从C中的路由器接收ICMP响应
【发布时间】:2011-02-03 15:48:17
【问题描述】:

我正在尝试编写一个 C 程序,该程序将 UDP 数据包发送到给定的 IP 地址并等待路由器的 ICMP 响应,告知生存时间已过期。它保持非常简单,因为我只想首先了解机制。我需要的是有人检查我的代码,并就错误和缺失提供反馈。我在 C 编程方面非常缺乏经验,但我必须将其作为一项任务来完成 - 尽我所能理解它......

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ip.h> 

// The packet length
#define PCKT_LEN 8192 

// Source IP, source port, target IP, target port from the command line arguments
int main(int argc, char *argv[])
{
    int send, recv, resp;
    int ttl = 1; // Time to live
    char buffer[PCKT_LEN];

    // Destination address
    struct sockaddr_in dst;

    // ICMP Response
    struct msghdr icmp;

    memset(buffer, 0, PCKT_LEN);

    // Create a raw socket with UDP protocol
    if ((send = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
        printf("Could not process socket() [send].\n");
        return EXIT_FAILURE;
    }

    // ICMP Socket
    if ((recv = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    {
        printf("Could not process socket() [recv].\n");
        return EXIT_FAILURE;
    }

    dst.sin_family      = AF_INET;
    dst.sin_addr.s_addr = inet_addr("74.125.39.106");
    dst.sin_port        = htons(60001);

    // Define time to life
    if(setsockopt(send, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0)
    {
        printf("Could not process setsockopt().\n");
        return EXIT_FAILURE;
    }

    if(sendto(send, buffer, sizeof(buffer), 0, (struct sockaddr *) &dst, sizeof(dst)) < 0)
    {
        printf("Could not process sendto().\n");
        return EXIT_FAILURE;
    }


    if((resp = recvmsg(recv, (struct msghdr *) &icmp, IP_RECVERR|MSG_ERRQUEUE)) < 0 )
    {
        printf("Could not process recvmsg().\n");
        return EXIT_FAILURE;
    }

    close(send);
    close(recv);

    return 0;
}

我不断收到“无法处理 recvmsg()”。我不知道还有什么可以尝试的。我希望收到 ICMP 答复并读取其发件人 IP 地址。

期待有用的提示。

最好的问候!

【问题讨论】:

  • recvfrom 的错误是什么?
  • 在 printf 之后添加对 perror 的调用以获取有关错误的更多信息 (linux.die.net/man/3/perror)。

标签: c sockets udp raw-sockets icmp


【解决方案1】:

我一般用

recvfrom(serversock, buf, 100, 0, (struct sockaddr *)&rcv,&size);

printf("Received packet from %s:%d\nData: %s\n\n", inet_ntoa(rcv.sin_addr), ntohs(rcv.sin_port), buf);

【讨论】:

  • 这就是我的代码缺少的所有魔力。太感谢了。我已经对此感到绝望了。
  • 使用getnameinfoNI_NUMERIC 将地址转换为可打印的数字形式。与inet_ntoa 不同,它不使用静态存储,因此它是线程安全的,并且可以安全地从库代码中使用。
猜你喜欢
  • 1970-01-01
  • 2012-01-23
  • 2019-01-04
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 2012-10-03
  • 2012-05-20
  • 1970-01-01
相关资源
最近更新 更多