如何使用C套接字ping

时间:2013-01-13 19:22:18

标签: c windows sockets ping icmp

  • 编译器:Code :: Blocks(GNU GCC)
  • 平台:Windows(x86)
  • 包含:winsock.h winsock2.h(ws2_32也链接)

我目前正在尝试编写一个程序,该程序将读取包含IP地址列表的文本文件并分别ping每个IP地址。如果主机响应ping,则主机的IP地址将被复制到用户指定的借调文件中。不经意的是,这是我第一次使用C的套接字库,我找不到一个关于如何使用C进行ping的好教程。据我所知,我找到了几个教程。我需要在IP数据报中包含一个ICMP头,它是一个包含ICMP类型,代码和校验和的结构。但我不知道该怎么做,我应该自己声明结构还是在头文件中声明?我假设它在一个标题中但是教程相互矛盾的确切地说明了它的位置。我厌倦了包括icmp.h和netinet / icmp.h但我的编译器抱怨它们不存在所以我创建了自己的结构。

    struct echo_request
    {
        char type; // Type
        char code; // Code
        short checksum; // Checksum
        short id; // Identification
        short seq; // Sequence
        int time; // Time
        char data[16]; // Data
    };

我认为我可以逃脱它,但我甚至无法编译我的程序,因为我的编译器说in_cksum()(校验和生成器)是未定义的。

总结一下我的问题,我应该包含哪些头文件,如何创建ping数据包,我使用正确的校验和生成器函数,ping是否应该指向端口80,并且我使用的套接字应该是RAW还是DGRAM?

这是我到目前为止所做的,请注意我故意遗漏了错误检查。

    int socket_descriptor = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);

    struct sockaddr_in address; //Initialize address struct
    memset(&address, 0, sizeof(address)); //Clear address struct

    //Declare address
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(ipaddress);
    address.sin_port = htons(80);

    //Bind socket to address
    bind(socket_descriptor, (struct sockaddr *)&address, sizeof(address));

    //Create packet
    struct echo_request packet; //See above for declaration of struct
    memset(packet.data, 1, 16);
    packet.type = 8; //ECHO_REQUEST
    packet.code = 0;
    packet.time = gettime();
    packet.checksum = 0;
    packet.checksum = in_cksum(packet, sizeof(packet));

2 个答案:

答案 0 :(得分:5)

如果您不必从头开始实施ping并且只需要Windows解决方案,那么我会提出第二个Anton对IcmpSendEcho的建议。如果必须实现ping,请查看如何实现POCO ICMP包。它是可移植的代码,在Windows上运行良好。

关于具体问题,以下是答案:

  

我应该包含哪些头文件

#include <winsock2.h>
  

如何创建ping数据包

有关IPv4数据包的示例,请参阅ICMPv4PacketImpl::initPacket()

  我正在使用正确的校验和生成器函数

不适用于Windows。有关校验和函数的示例,请参阅ICMPPacketImpl::checksum()

  

应该将ping定向到端口80

没有。在ICMP方面没有端口这样的东西。见Does ICMP use a specific port?

  

我使用的套接字应该是RAW还是DGRAM

应该是RAW。

答案 1 :(得分:4)

看起来你想要一个真正的解决方案,而不仅仅是为了重新实现PING。

我建议使用IP帮助程序(在WinXP之前的系统上使用ICMP.dll),特别是IcmpSendEcho(或其增强版本IcmpSendEcho2IcmpSendEcho2Ex,用于异步操作。 / p>

在MSDN上有一个“ping”主机的完整示例。这可能是一个很好的起点。

更新:对于GCC(mingw),请链接-liphlpapi。