Рассылка закрыта
При закрытии подписчики были переданы в рассылку "О карьере и профессиональном развитии IT-специалистов" на которую и рекомендуем вам подписаться.
Вы можете найти рассылки сходной тематики в Каталоге рассылок.
← Февраль 2005 → | ||||||
1
|
2
|
3
|
4
|
5
|
6
|
|
---|---|---|---|---|---|---|
7
|
8
|
9
|
10
|
11
|
12
|
13
|
14
|
15
|
16
|
17
|
18
|
20
|
|
21
|
22
|
23
|
24
|
25
|
26
|
27
|
28
|
Статистика
-4 за неделю
Программирование для начинающих и не только
Информационный Канал Subscribe.Ru |
По материалам сайта www.gigabyte.iatp.org.ua
Trace route своими руками
Trace route - одна из важнейших команд, использующихся при настройке и отладке сетей любых масштабов и топологий. В этой статье мы рассмотрим методы организации операции trace route при помощи Delphi.
Теория
Функция, Trace route позволяет выявлять последовательность шлюзов, через которую проходит IP-пакет на пути к пункту своего назначения, в том или ином виде представлена в любой современной операционной системе и реализована как при помощи программы командной строки так и в качестве библиотечной функции . Эта команда имеет очень много опций, большинство из которых в повседневной работе не применяются. Как обычно, имя машины, которое может быть задано в символической или числовой форме. Выходная информация - список машин, начиная с первого шлюза и заканчивая пунктом назначения.
Команда traceroute (traceroute.exe для Windows) работает путем установки поля времени жизни (числа переходов) исходящего пакета таким образом, чтобы это время истекало до того, как пакет достигнет пункта назначения. Когда время жизни истечет, текущий шлюз должен послать сообщение об ошибке на машину-источник. Каждое приращение поля времени жизни позволяет пакету пройти на один шлюз дальше.
Команда traceroute посылает для каждого значения поля времени жизни три пакета. Если промежуточный шлюз распределяет трафик по нескольким маршрутам, то эти пакеты могут возвращаться разными машинами, в этом случае traceroute просто печатает их все. Некоторые системы не посылают уведомлений о пакетах, время жизни которых истекло, а некоторые посылают уведомления, которые поступают обратно на машину-источник только после того, как traceroute перестала их ждать. Эти "таинственные шлюзы" обозначаются рядом звездочек. Даже если конкретный шлюз определить нельзя, traceroute все равно сможет увидеть следующие за ним узлы маршрута.
Практика
Практическая реализация команды traceroute в Delphi как всегда может быть реализована несколькими способами и наиболее простой из них это использование компонентов предоставляемых сторонними производителями (т.к. в компонентах Indy я не нашел соответствующего компонента, или может не там искал), и конечно же можно использовать Windows API. О достоинствах и недостатках той или иной реализации этой функции можно судить исходя из ваших потребностей, возможностей и времени. Так если вы даже отдаленно не представляете себе как надо работать с Windows API то лучшим вариантом для вас будет скачать из сети соответствующий компонент и использовать его. Этот же вариант можно использовать если вам срочно (в течении 2-3 часов) необходимо реализовать простенькое приложение, которое бы выполняло trace route. Но если вы не стеснены во времени или должны написать критическое по времени выполнения приложение, то тогда вам следует позаботится о правильной реализации функции traceroute с использованием Windows API. И конечно же после того, как вы основательно разобрались с WinAPI, то следующим шагом станет написание компонента которые бы брал на себя всю грязную работу оставляя вам только обработку чистых результатов отслеживания.>
Windows API
К сожалению в Windows вы не сможете найти такую библиотеку, которая бы прямо экспортировала функцию traceroute (а если и найдете, то это будет уже изюминка Вашей Windows и не стоит ее использовать т.к. вы не знаете будет ли такая "изюминка" и в других Windows-ах).
Для реализации traceroute мы воспользуемся уже известной нам библиотекой icmp.dll[1]. Здесь же нам придется применить смекалку и воспользоваться алгоритмом приведенным в первом разделе для написания функции traceroute.
Итак, для написания функции которая бы отслеживала адреса шлюзов через которые переходит пакет мы для начала в Delphi организуем новое приложение, в котором разместим кнопку и компонент TListBox. Далее по алгоритму мы будем пинговать адрес (к примеру www.mail.ru: 194.67.57.51) с заданными параметром TTL = 1, и выведем результат, далее пингуем хост при TTL=2 3 4 и т.д. Применение такого алгоритма будет нам последовательно возвращать IP-адрес каждого шлюза через который прошел пакет. И для того, чтобы не возится
каждый раз с открыванием и накрыванием хэндлов мы сперва напишем функцию PingAlt (несколько переработанный аналог функции ping из [1]), которая в качестве дополнительного параметра будет принимать структуру TOption_Information одним из полей которого и есть уже упомянутый TTL, параметр, который в нашем случае будет играть главную роль при работе нашей программы. Сама функция PingAlt выглядит следующим образом:
procedure PingAlt(const Address,EchoString:PChar;var PingReply:TsmICMP_Echo_Reply;Options:TOption_Information; const PingTimeout:integer=5000); var IpAddress:TIPAddr; icmpport:THandle; begin IpAddress:=inet_addr(Address); if (ipaddress=INADDR_NONE) then raise Exception.Create('Function call inetaddr failed. with Address '+Address); icmpport:=IcmpCreateFile; if (icmpport=invalid_handle_value) then raise Exception.Create('icmpCreateFile Failed'); icmpSendEcho (icmpport,ipaddress,EchoString,Length(EchoString),@Options,@PingReply,SizeOf(PingReply),PingTimeout); IcmpCloseHandle(icmpport); end;
Кроме того, для вывода результатов работы мы напишем еще одну функцию, которая будет преобразовывать IP-адрес в понятный для нас вид:
function ip2string(ip_address:longint):string; begin ip_address:=winsock.ntohl(ip_address); result:= inttostr(ip_address shr 24)+'.'+ inttostr((ip_address shr 16) and $ff)+'.'+ inttostr((ip_address shr 8) and $ff)+'.'+ inttostr(ip_address and $ff); end;
Теперь нам потребуется только правильно организовать цикл для отслеживания всех шлюзов, который можно написать следующим образом:
procedure TForm1.Button2Click(Sender: TObject); var Options:TOption_Information; Reply:TsmICMP_Echo_Reply; i:integer;Buf:Array[0..127] of Char; begin ZeroMemory(@Options,SizeOf(Options)); FillChar(Buf,SizeOf(Buf),#123); Options.Ttl:=255; PingAlt('194.67.57.51',@Buf,Reply,Options,5000); Listbox1.Items.Add(IntToStr(REply.RoundTripTime)+':'+IntToStr(Reply.Options.Ttl)); i:=1; ZeroMemory(@Reply,SizeOf(Reply)); while (Reply.Status<>IP_SUCCESS) or (ip2string(REply.Address)<>'194.67.57.51') do begin options.Ttl:=i; PingAlt('194.67.57.51',@Buf,Reply,Options,5000); LIstBox1.Items.Add(ip2string(Reply.Address)+':'+IntToStr(Reply.RoundTripTime)); inc(i); Application.ProcessMessages; end; end;
Теперь после нажатия кнопки у нас в списке сперва появится строка с отпингованным временем и свойством TTL для адреса mail.ru. А дальше последовательно будут появляться адреса шлюзов по которым проходят пакет до конечного адреса. Все приложение готово.
Что еще осталось
Конечно описанное выше демонстрационное приложение далеко от идеала и по своим дизайнерским(рис.1) и по функциональным качествам. Так для использования этого приложение вам придется вводить только IP-адреса так как она пока что не в состоянии сама определить IP для хоста заданного именем. Для того, чтобы преодолеть этот недосмотр самым легким способом, мы можем воспользоваться методом WSGetHostByName из объекта GStack, определенного в модуле idStack, который поставляется вместе с Delphi. Если же вы желаете использовать только WinAPI, то лучший способ - заглянуть в модуль idStackWinsock.pas где расположен код реализации этой функции для Windows.
Листинг.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); // 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 Type 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.
http://subscribe.ru/
http://subscribe.ru/feedback/ |
Подписан адрес: Код этой рассылки: comp.soft.prog.programmershelp |
Отписаться |
В избранное | ||