我目前正在尝试编写一个程序,该程序将读取包含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));
答案 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(或其增强版本IcmpSendEcho2
,IcmpSendEcho2Ex
,用于异步操作。 / p>
在MSDN上有一个“ping”主机的完整示例。这可能是一个很好的起点。
更新:对于GCC(mingw),请链接-liphlpapi。