Как написать программу ping

Команда PING это, пожалуй, самая используемая сетевая утилита командной строки. PING присутствует во всех версиях всех операционных систем с поддержкой сети и является простым и удобным средством опроса узла по имени или его IP-адресу.

Для обмена служебной и диагностической информацией в сети используется специальный протокол управляющих сообщений ICMP (Internet Control Message Protocol). Команда ping позволяет выполнить отправку управляющего сообщения типа Echo Request (тип равен 8 и указывается в заголовке ICMP-сообщения) адресуемому узлу и интерпретировать полученный от него ответ в удобном для анализа виде. В поле данных отправляемого icmp-пакета обычно содержатся символы английского алфавита. В ответ на такой запрос, опрашиваемый узел дожжен отправить icmp-пакет с теми же данными, которые были приняты, и типом сообщения Echo Reply (код типа в ICMP-заголовке равен 0) . Если при обмене icmp-сообщениями возникает какая-либо проблема, то утилита ping выведет информацию для ее диагностики.

Как создать Android игру за 10 минут на языке Python!

Формат командной строки:

Источник: ab57.ru

Как написать программу ping

Команда ping служит для принудительного вызова ответа конкретной машины. Для этого используется дейтаграмма ECHO_REQUEST протокола ICMP. Это протокол низкого уровня, который не требует наличия серверных процессов на зондируемой машине; это хороший способ убедится в том, что питание машины включено и IP находится в поднятом состоянии. Успешный результат использования команды ping вовсе не обязательно означает, что выполняются какие-то сервисные программы высокого уровня.

Ping — хорошее средство проверки правильности конфигурации сети, поскольку в выполнении этой команды участвуют система маршрутизации, схемы разрешения адресов и сетевые шлюзы. Если данная команда не работает — можете быть совершенно уверены, что более сложные средства тем более не функционируют. Несмотря на свою простоту, ping — одна из главных рабочих лошадок, использующихся при отладке сетей.

Практика

Для практической реализации, как всегда, можно использовать несколько подходов. Первый из них — использование низкоуровневых функций API (к примеру, встроенных в библиотеку ICMP.DLL). Второй — использование высокоуровневых компонентов (к примеру, Indy IdICMPClient).

И у первого, и у второго способа есть свои позитивные и негативные моменты. Так, при использовании функций API откомпилированный код будет иметь гораздо меньшие размеры, нежели при использовании высокоуровневых компонентов,- да и производительность его будет выше (например, при одновременном пинге одной подсети с использованием потоков).

С другой стороны, компоненты можно использовать, имея только отдаленное представление о работе с протоколом ICMP, а также об использовании Windows API. Но, в то же время, компоненты порождают неоправданно большой исполняемый код, да и производительность в этом случае ниже. К счастью, сегодня разработчиками процессоров и памяти почти стерта грань между производительностью кода, написанного с использованием Windows API, и кода, написанного с использованием средств более высокого уровня абстракции (в нашем случае — компонентов Delphi).

Команда Ping или проверка работоспособности сети

На всякий случай приведем примеры пинга, написанного как с использованием WinAPI так и с использованием компонентов Indy.

Windows API

При использовании Windows API для написания функции пинга воспользуемся библиотекой ICMP (icmp.dll), которая предоставляет интерфейс для работы с одноименным протоколом. В этой библиотеке реализованы три функции, с которыми в дальнейшем мы будем работать. В интерпретации Delphi их объявления выглядят следующим образом:

function IcmpCreateFile:Thandle; StdCall;

function IcmpCloseHandle (H:Thandle):Bool; StdCall;

function IcmpSendEcho (IcmpHandle:Thandle;
DestinationAddress:TipAddr;
RequestData:pointer;
RequestSize:word;
RequestOptions:POption_Information;
ReplyBuffer:pointer;
ReplySize:integer;
Timeout:integer):Integer; stdcall;

Первая из них (IcmpCreateFile) создает соединение, с которым мы собираемся работать. Вторая закрывает его, а третья посылает через установленное соединение соответствующие данные.

  • IcmpHandle — идентификатор соединения, установленного при помощи IcmpCreateFile;
  • DestinationAddress — адрес пингуемого хоста;
  • RequestData — буфер с данными, которые посылаются при запросе;
  • RequestSize — размер буфера запроса;
  • RequestOptions — дополнительные свойства запроса;
  • ReplyBuffer — адрес буфера для приема результата;
  • ReplySize — размер буфера приема;
  • Timeout — время, в течение которого мы ожидаем ответа от хоста;
  • результат функции — количество записей типа ICMP_ECHO_REPLY, сохраненных в ReplyBuffer. Статус каждой записи хранится в соответствующем поле этой записи. При неудачном вызове функция возвращает значение NULL; дополнительная информация доступна при вызове GetLastError.
Читайте также:
Программа для обновления видеокарты nvidia geforce

Структура ICMP_ECHO_REPLY имеет следующий вид:

Ticmp_echo_reply=record
Address: TipAddr; // Ответивший адрес
Status: integer; // Статус ответа
RoundTripTime: integer; // Время прохождения пакета
DataSize: word; // Размер данных ответа в байтах
Reserved: word; // Зарезервировани
Data: pointer; // Указатель на буфер с ответом
Options: Toption_Information; // Опции ответа.
End;

Помимо нее, мы можем использовать расширенный вариант структуры ICMP_ECHO_REPLY:

TsmICMP_Echo_Reply=record
Address: TipAddr; // Ответивший адрес
Status: integer; // Статус ответа
RoundTripTime: integer; // Время прохождения пакета
DataSize: word; // Размер данных ответа в байтах
Reserved: word; // Зарезервировани
Data: pointer; // Указатель на буфер с ответом
Options: Toption_Information; // Опции ответа.
Data: array [0..255] of Char;
end;

  • создаем соединение;
  • вызываем ICMPSendEcho;
  • обрабатываем результат;
  • закрываем соединение.

Эти действия удобно оформить в виде процедуры:

Теперь при использовании в коде программы конструкции:

в переменной Reply мы получим результат пинга.

Использование Indy

Те, кто не знакомы с практикой программирования с использованием Windows API, могут воспользоваться встроенными в Delphi компонентами для работы с сетью. В частности, для реализации пинга на уровне объектно-ориентированного программирования воспользуемся компонентом IdICMPClient из состава Indy.

Для этого создадим сначала на пустой форме экземпляр класса TIdICMPClient, перетащив его с палитры компонентов Indy Clients. Затем поместим на форму стандартную кнопку (TButton) и в ее реакции на нажатие мышкой запишем код:

Self.IdIcmpClient1.Host:=’localhost’;//вместо 127.0.0.1 здесь можно использовать имя «localhost»
Self.IdIcmpClient1.Ping;

И не забудем выставить соответствующий интервал ожидания ответа, по завершении которого (или при получении данных от пингуемого) вызывается обработчик:

TidIcmpClient.OnReply (Sender:TComponent; const AReplyStatus:TReplyStatus);

— в котором мы реализуем вывод данных пинга на экран:

procedure TForm1.IdIcmpClient1Reply (ASender: TComponent;
const AReplyStatus: TReplyStatus);
begin
ListBox1.Items.Add (‘Reply:’+IntToStr (AReplyStatus.MsRoundTripTime));
end;

Послесловие

Конечно, для пинга удаленной машины вы всегда можете обратиться к соответствующей программе командной строки, поскольку 100% операционных систем поддерживает эту команду. Но не всегда дело ограничивается одним пингом — особенно если вы реализуете собственный интерфейс поверх IP. В таком случае вызов внешней программы при каждой проверке — слишком большая роскошь.

Кроме того, поняв, как работать с ICMP, вы сможете использовать эти возможности и в других — в том числе и «военных» — целях.

Листинг 1. Определения функций ICMP.DLL

unit icmp;
interface
uses windows;
Const
// IP_STATUS codes returned from IP APIs

IP_STATUS_BASE = 11000;
IP_SUCCESS = 0;
IP_BUF_TOO_SMALL = (IP_STATUS_BASE + 1);
IP_DEST_NET_UNREACHABLE = (IP_STATUS_BASE + 2);
IP_DEST_HOST_UNREACHABLE = (IP_STATUS_BASE + 3);
IP_DEST_PROT_UNREACHABLE = (IP_STATUS_BASE + 4);
IP_DEST_PORT_UNREACHABLE = (IP_STATUS_BASE + 5);
IP_NO_RESOURCES = (IP_STATUS_BASE + 6);
IP_BAD_OPTION = (IP_STATUS_BASE + 7);
IP_HW_ERROR = (IP_STATUS_BASE + 8);
IP_PACKET_TOO_BIG = (IP_STATUS_BASE + 9);
IP_REQ_TIMED_OUT = (IP_STATUS_BASE + 10);
IP_BAD_REQ = (IP_STATUS_BASE + 11);
IP_BAD_ROUTE = (IP_STATUS_BASE + 12);
IP_TTL_EXPIRED_TRANSIT = (IP_STATUS_BASE + 13);
IP_TTL_EXPIRED_REASSEM = (IP_STATUS_BASE + 14);
IP_PARAM_PROBLEM = (IP_STATUS_BASE + 15);
IP_SOURCE_QUENCH = (IP_STATUS_BASE + 16);
IP_OPTION_TOO_BIG = (IP_STATUS_BASE + 17);
IP_BAD_DESTINATION = (IP_STATUS_BASE + 18);

// The next group are status codes passed up on status indications to
// transport layer protocols.
IP_ADDR_DELETED = (IP_STATUS_BASE + 19);
IP_SPEC_MTU_CHANGE = (IP_STATUS_BASE + 20);
IP_MTU_CHANGE = (IP_STATUS_BASE + 21);
IP_UNLOAD = (IP_STATUS_BASE + 22);
IP_GENERAL_FAILURE = (IP_STATUS_BASE + 50);
MAX_IP_STATUS = IP_GENERAL_FAILURE;
IP_PENDING = (IP_STATUS_BASE + 255);

Читайте также:
Как скомпилировать программу на python

// Values used in the IP header Flags field.
IP_FLAG_DF = $2; // Don’t fragment this packet.

// Supported IP Option Types.
// These types define the options which may be used in the OptionsData field
// of the ip_option_information structure. See RFC 791 for a complete
// description of each.
IP_OPT_EOL = 0; // End of list option
IP_OPT_NOP = 1; // No operation
IP_OPT_SECURITY = $82; // Security option
IP_OPT_LSRR = $83; // Loose source route
IP_OPT_SSRR = $89; // Strict source route
IP_OPT_RR = $7; // Record route
IP_OPT_TS = $44; // Timestamp
IP_OPT_SID = $88; // Stream ID (obsolete)

MAX_OPT_SIZE = 40; // Maximum length of IP options in bytes

TIPAddr=integer; // An IP address.
TIPMask=integer; // An IP subnet mask.
TIP_STATUS=Integer; // Status code returned from IP APIs.

POption_Information=^TOption_Information;
TOption_Information=record
Ttl:byte; // Time To Live
Tos:byte; // Type Of Service
Flags:byte; // IP header flags
OptionsSize:byte; // Size in bytes of options data
OptionsData:pointer; // Pointer to options data
end;
Picmp_echo_reply=^Ticmp_echo_reply;
Ticmp_echo_reply=record
Address:TipAddr; // Replying address
Status:integer; // Reply IP_STATUS
RoundTripTime:integer; // RTT in milliseconds
DataSize:word; // Reply data size in bytes
Reserved:word; // Reserved for system use
Data:pointer; // Pointer to the reply data
Options:Toption_Information; // Reply options
end;
TsmICMP_Echo_Reply=record
Address:TipAddr; // Replying address
Status:integer; // Reply IP_STATUS
RoundTripTime:integer; // RTT in milliseconds
DataSize:word; // Reply data size in bytes
Reserved:word; // Reserved for system use
DataPtr:pointer; // Pointer to the reply data
Options:Toption_Information; // Reply options
Data: array [0..255] of Char;
end;

function IcmpCreateFile:Thandle; StdCall;
function IcmpCloseHandle (H:Thandle):Bool; StdCall;
function IcmpSendEcho (IcmpHandle:Thandle;DestinationAddress:TipAddr;
RequestData:pointer;RequestSize:word;
RequestOptions:POption_Information;ReplyBuffer:pointer;
ReplySize:integer;Timeout:integer):Integer; stdcall;
Implementation
function IcmpCreateFile; external ‘Icmp.Dll’;
function IcmpCloseHandle; external ‘Icmp.Dll’;
Function IcmpSendEcho; external ‘Icmp.Dll’;
end.

Листинг 2. Процедура «пинга»

function PingStatusToStr (StatusCode: integer): string;
begin
case (StatusCode) of
IP_SUCCESS: Result:= ‘IP_SUCCESS’;
IP_BUF_TOO_SMALL: Result:= ‘IP_BUF_TOO_SMALL’;
IP_DEST_NET_UNREACHABLE: Result:= ‘IP_DEST_NET_UNREACHABLE’;
IP_DEST_HOST_UNREACHABLE: Result:= ‘IP_DEST_HOST_UNREACHABLE’;
IP_DEST_PROT_UNREACHABLE: Result:= ‘IP_DEST_PROT_UNREACHABLE’;
IP_DEST_PORT_UNREACHABLE: Result:= ‘IP_DEST_PORT_UNREACHABLE’;
IP_NO_RESOURCES: Result:= ‘IP_NO_RESOURCES’;
IP_BAD_OPTION: Result:= ‘IP_BAD_OPTION’;
IP_HW_ERROR: Result:= ‘IP_HW_ERROR’;
IP_PACKET_TOO_BIG: Result:= ‘IP_PACKET_TOO_BIG’;
IP_REQ_TIMED_OUT: Result:= ‘IP_REQ_TIMED_OUT’;
IP_BAD_REQ: Result:= ‘IP_BAD_REQ’;
IP_BAD_ROUTE: Result:= ‘IP_BAD_ROUTE’;
IP_TTL_EXPIRED_TRANSIT: Result:= ‘IP_TTL_EXPIRED_TRANSIT’;
IP_TTL_EXPIRED_REASSEM: Result:= ‘IP_TTL_EXPIRED_REASSEM’;
IP_PARAM_PROBLEM: Result:= ‘IP_PARAM_PROBLEM’;
IP_SOURCE_QUENCH: Result:= ‘IP_SOURCE_QUENCH’;
IP_OPTION_TOO_BIG: Result:= ‘IP_OPTION_TOO_BIG’;
IP_BAD_DESTINATION: Result:= ‘IP_BAD_DESTINATION’;
IP_ADDR_DELETED: Result:= ‘IP_ADDR_DELETED’;
IP_SPEC_MTU_CHANGE: Result:= ‘IP_SPEC_MTU_CHANGE’;
IP_MTU_CHANGE: Result:= ‘IP_MTU_CHANGE’;
IP_UNLOAD: Result:= ‘IP_UNLOAD’;
IP_GENERAL_FAILURE: Result:= ‘IP_GENERAL_FAILURE’;
else
Result:= ‘ ‘;
end;
end;

function inet_addr; external ‘WSock32.Dll’;

Листинг 3. Демонстрация пингов

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
IdIcmpClient, StdCtrls, IdUDPBase, IdUDPClient, IdSNTP;

type
TForm1 = class (TForm)
Button1: TButton;
ListBox1: TListBox;
IdIcmpClient1: TIdIcmpClient;
IdSNTP1: TIdSNTP;
procedure Button1Click (Sender: TObject);
procedure IdIcmpClient1Reply (ASender: TComponent;
const AReplyStatus: TReplyStatus);
private

public

end;

var
Form1: TForm1;

implementation
uses pingModule,icmp;

procedure TForm1.Button1Click (Sender: TObject);
var Reply:TsmICMP_Echo_Reply;
begin
Self.IdIcmpClient1.Host:=’localhost’;
Self.IdIcmpClient1.TTL:=192;
Self.IdIcmpClient1.Ping;
Ping (‘127.0.0.1’,nil,Reply,5000);
ListBox1.Items.Add (‘RawReply:’+IntToStr (Reply.RoundTripTime));
end;

procedure TForm1.IdIcmpClient1Reply (ASender: TComponent;
const AReplyStatus: TReplyStatus);
begin
ListBox1.Items.Add (‘Reply:’+IntToStr (AReplyStatus.MsRoundTripTime));
end;

Источник: citforum.ru

C++, ping и traceroute

Изучая сетевое программирование и имея в портфолио несколько проектиков на C++, связанных с сетевым программированием, я решил написать что-нубудь, что будет иметь реальное практическое применение.

Первое, что мне пришло в голову — утилита ping.

Ping — утилита для проверки целостности и качества соединений в сетях на основе TCP/IP, а также обиходное наименование самого запроса

Я подумал, что почитав доки: https://www.rfc-editor.org/rfc/rfc792, смогу написать собственную имплементацию.

Ping

В принципе, алгоритм прост и понятен: отправляешь пакет и засекаешь время до ответа.

Читайте также:
Программы как radmin vpn

Спустя несколько дней был готов приемлемый вариант ping-а, который есть на Github.

Для понимания работы traceroute необходимо иметь представление о работе ping-а, так что разбор некоторых строк кода не повредит.

pid_t ppid = getppid();

В этой строчке мы получаем идентификатор потока нашего ping-a, которому выделено поле в протоколе ICMP.

Далее создается структура ICMP заголовка:

struct icmpHeader < uint8_t type; uint8_t code; uint16_t checksum; union < struct < uint16_t identifier; uint16_t sequence; uint64_t payload; >echo; struct ICMP_PACKET_POINTER_HEADER < uint8_t pointer; >pointer; struct ICMP_PACKET_REDIRECT_HEADER < uint32_t gatewayAddress; >redirect; > meta; >;

Поля type, code, checksum — обязательные. В пинге мы использовали только echo, структура из 7 — 11 строк, но другие структуры — осколки имплементации ICMP, которые в принципе можно было бы убрать. В дальнейшем те же структуры будут использоваться и в traceroute.

Далее идет функция генерации интернет-чексуммы:

uint16_t checksum(const void *data, size_t len) < auto p = reinterpret_cast(data); uint32_t sum = 0; if (len sum = reinterpret_cast(p)[len — 1]; > len /= 2; while (len—) < sum += *p++; if (sum sum = (sum >> 16) + (sum > > return static_cast(~sum); >

После отправки пакета, нам нужно засечь время, которое пакет шел от нас к цели и обратно:

long int send_flag = sendto(sock, in_addr, socklen_t(sizeof(in_addr))); sent++; uint64_t ms_before = duration_cast(system_clock::now().time_since_epoch()).count(); if (send_flag < 0) < perror(«send error»); return; >char buf[1024]; auto *icmpResponseHeader = (struct icmpHeader *) buf; struct timeval tv; tv.tv_sec = response_timeout; tv.tv_usec = 0; setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, int data_length_byte = recv(sock, icmpResponseHeader, sizeof(buf), 0); if(data_length_byte == -1) < cout uint64_t ms_after = duration_cast(system_clock::now().time_since_epoch()).count();

Строки создания пакета и присваивания его полям значений опущены, так как не содержат критически важной информации. Стоит отметить только, что ICMP выделяет поле для бинарных данных, которые в коде заполнены набором единиц и нулей.

Traceroute

Traceroute — это служебная компьютерная программа, предназначенная для определения маршрутов следования данных в сетях TCP/IP.

Для начала, я проанализировал пакеты оригинального линуксового traceroute Wireshark-ом.

Поскольку отправка «сырых» пакетов требует рут-привилений, traceroute использует UDP, отправляя пакеты с увеличивающися TTL на рандомный порт цели и ждет получения ответа о закрытости порта.

Все же я подумал, что писать на ICMP будет проще, хоть и для запуска нужен будет рут.

Traceroute отправляет эхо-пакеты с увеличивающимся TTL. TTL — Time To Live, время жизни пакета и по дефолту он равен 30. Время жизни пакета уменьшается после прохождения им каждого узла в сети. Допустим, мы хотим найти маршрут до 1.1.1.1:

Если отправить пакет с TTL 1, то он упрется в первый узел (обычно в ваш роутер 192.168.0.1 или в подсеть) и тот вернет ответ: TTL exceeded, что значит «время жизни истекло». Из его ответа можно вытащить ip_src и таким образом узнать IP-адрес первого узла. Взяв TTL 2, можно узнать IP-адрес второго узла и т.д

Меняется тип пакета (8) и каждую итерацию цикла увеличивается TTL.

icmp_packet.type = 8; icmp_packet.code = 0; icmp_packet.checksum = 0; icmp_packet.meta.echo.identifier = ppid; icmp_packet.meta.echo.sequence = i; icmp_packet.meta.echo.payload = 0b101101010110100101; // random binary data icmp_packet.checksum = checksum(
int ttl = i + 1; setsockopt(sock, IPPROTO_IP, IP_TTL,

В следующем коде мы проверяем, от кого пришел ответ — от цели или нет. Если от цели, то прерываем цикл и показываем результаты.

if (strcmp(inet_ntoa(src_addr.sin_addr), ip) == 0)

Я считаю, что traceroute и ping — утилиты, которые улучшат портфолио и помогут глубже разобраться с сетевым программированием. В любом случае для общего развития рекомендую прочитать https://www.rfc-editor.org/rfc/rfc791 (про протокол IP).

  • network
  • linux development

Источник: habr.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru