Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.118.226.105] |
|
Сообщ.
#1
,
|
|||||||||||
|
Протокол Ping предназначен для тестирования компьютерных соединений в Интернете путём посылки через протокол Internet Protocol (IP) по обределённому адресу сообщения и ожидания от него ответа. ICMP - Internet Control Message Protocol. ICMP служит для передачи сообщений об ошибках а так же управляющих сообщений . ICMP-тест может показать насколько быстро проходит информация между двумя узлами в Интернете. 1. Запускаем Delphi; 2. В Новом проекте добавляем в форму Tbutton, Tedit и Tmemo; 3. Вставляем “winsock”; 4. объявляем структурку для IP-заголовка:
5. объявляем структурку для хранения ICMP пакета:
6. Объявляем функции и процедуры, которые мы будем вызывать из ICMP.DLL
7. В Tbutton в событие Onclick вставляем следующий код:
У данного примера есть один недостаток - программа не воспримет доменное имя, только IP-адресс. Для пользователей NT не используйте функцию IcmpCloseHandle. Это всё….. Ну и в конце полный исходный код примера:
|
Сообщ.
#2
,
|
|
|
еще одна реализация ping (запрос - ожидание ответа)
На форме использовал одно Memo, для конторля. Для запуска программы на системе NT необходимы права администратора. Заголовог icmphead = record icmp_type: byte; icmp_code: byte ; icmp_chksum: word; icmp_id: word; icmp_seq: word; icmp_data: array [0..55] of byte; // можно больше а можно и меньше end; сама функция пинга (параметр - ip который надо пингануть). function ping(ip: DWORD): bool; var s: integer; pid: WORD; sai: tsockaddrin; size: integer; icmp: icmphead; len: integer; flag: bool; buf: array [0..255] of byte; picmp: ^icmphead; begin flag:=false; pid:=word(GetCurrentProcessId); s:=socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if(s<0) then form1.Memo1.Lines.Add('socket error'); // это так для теста, если вдруг сокет не создан FillChar(sai, sizeof(sai), 0); sai.sin_family:=AF_INET; sai.sin_addr.S_addr:=inet_addr(ip); connect(s, sai, sizeof(sai)); icmp.icmp_type := 8; icmp.icmp_code := 0; icmp.icmp_id := pid; icmp.icmp_seq := 1; len := sizeof(icmp); icmp.icmp_chksum := 0; icmp.icmp_chksum := in_cksum(icmp, len); send(s, icmp, sizeof(icmp), 0); // посылаем while not flag do begin recv(s, buf, 256, 0); // AHTUNG!!! вот тут тайм аут нужен. // Можно SO_RCVTIMEO сокету поставить. иначе прога застынет // "навсегда" в случае не ответа picmp:=@buf[20]; form1.memo1.Lines.Add('recv '+ inttostr(picmp^.icmp_id)+' '+ inttostr(pid)); // это для контроля flag:=(picmp^.icmp_id=pid); // это наш ответ? end; result:=picmp^.icmp_type; // возвращаем тип ICMP, если он 0 то это ответ. end; рассчет контроьной суммы (взято из Linux и переведено на делфи) function in_cksum(var buf; len:integer):word; var p: pointer; sum: longint; i: integer; begin p:=@buf; sum:=0; for i:=1 to len div 2 do begin sum:=sum+word(p^); p:=pointer(longint(p)+2); end; if len mod 1<>0 then sum:=sum+byte(p^); sum:=(sum shr 16) + (sum and $ffff); sum:=sum+(sum shr 16); result:=word(NOT sum); end; все - проверено, работает. |