- 编译器: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));