Как пинговать с помощью сокетов C

  • компилятор: код:: блоки (GNU GCC)
  • Платформа: Windows (x86)
  • включает в себя: winsock.ч в winsock2.h (ws2_32 также связан)

в настоящее время я пытаюсь написать программу, которая будет читать текстовый файл, содержащий список IP-адресов и ping каждого IP-адреса соответственно. Если хост отвечает на ping, то IP-адрес хоста будет скопирован во второй файл, указанный пользователем. Unfourtantly это первый раз, когда я используется библиотека сокетов C, и я не могу найти хороший учебник о том, как пинговать с помощью C. Из того, что я понимаю из пары учебников, которые я нашел. Мне нужно включить заголовок ICMP, который является структурой, содержащей тип ICMP, код и контрольную сумму, в датаграмме IP. Но я понятия не имею, как это сделать, должен ли я объявить структуру сам или она объявлена в файле заголовка? Я предполагаю, что он находится в заголовке, но учебники противоречили друг другу о том, где именно он объявлен. Я устал в том числе протоколу ICMP.h и netinet / icmp.ч но мой компилятор жаловался, что они не существуют, поэтому я создал свою собственную структуру.

    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 ответов


Если вам не нужно реализовывать ping с нуля, и вы хотите только решение Windows, я бы поддержал предложение Антона для IcmpSendEcho. Если вам нужно реализовать ping, посмотрите, как поко пакет ICMP реализован. Это портативный код, и он отлично работает в Windows.

что касается конкретных вопросов, вот ответы:

какие заголовочные файлы я должен включить

#include <winsock2.h>

Как создать пакет ping

посмотреть ICMPv4PacketImpl:: initPacket() для примера пакета IPv4.

Я использую правильную функцию генератора контрольной суммы

Не для windows. См.ICMPPacketImpl::контрольная сумма() пример функции checksum.

должен ли пинг быть направлен на порт 80

нет. Нет такой вещи, как порт, когда дело доходит до ICMP. См.тут ICMP использует определенный порт?

должен ли сокет, который я использую, быть RAW или DGRAM

Он должен быть сырым.


похоже, вам нужно реальное решение, а не просто переопределение PING ради него.

Я рекомендую использовать IP helper (ICMP.dll на системах pre-WinXP), в частности,IcmpSendEcho (или его расширенной версии, IcmpSendEcho2, IcmpSendEcho2Ex, для асинхронных операций).

существует полный пример "pinging" хоста на MSDN. Это может быть хорошей отправной точкой.

обновление: для GCC (mingw), ссылка с-liphlpapi.