Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2003.11.13;
Скачать: CL | DM;

Вниз

Програмный PING   Найти похожие ветки 

 
SiONYX   (2003-09-04 23:57) [0]

Идея следующая: прежде чем пытаться соединиться с удаленной машиной - пропинговать ее. Если отзовется => включена и можно соединиться. (А то если машина выключена - попытка коннекта "затягивается").

Есть хорошая утилитка PING, но как бы зделать что-то подобное програмно.

Может кто посоветует что-то другое реализующее эту идею.

Заранее спасибо.


 
Вася Пупкин ©   (2003-09-05 01:04) [1]

А что мешает написать ping ? программно ? -)


 
Вася Пупкин ©   (2003-09-05 01:13) [2]

Вот "сырой" пример... разбирайся если есть такое желание

//******************************************************************** **********\
// Simple ping utility using SOCK_RAW
//******************************************************************** **********/
program Ping;
{$APPTYPE CONSOLE}
uses
windows, winsock2;
const
ICMP_ECHO = 8;
ICMP_ECHOREPLY = 0;
ICMP_MIN = 8; // minimum 8 byte icmp packet (just header)
STATUS_FAILED = $FFFF;
DEF_PACKET_SIZE = 32;
MAX_PACKET = 1024;

type

// IP header
PIpHeader=^TIpHeader;
TIpHeader = packed record
VerLen : byte;
tos : byte; // Type of service
total_len : word; // total length of the packet
ident : word; // unique identifier
frag_and_flags : word; // flags
ttl : byte;
proto : byte; // protocol (TCP, UDP etc)
checksum : word; // IP checksum
sourceIP : DWORD;
destIP : DWORD;
end;

// ICMP header
PIcmpHeader=^TIcmpHeader;
TIcmpHeader = packed record
i_type : byte;
i_code : byte; // 0 * type sub code */
i_cksum : word; //0
i_id : word;
i_seq : word;
// This is not the std header, but we reserve space for time
timestamp : DWORD;
end;

var
wsaData : TWSADATA;
Dest, From : TSockAddrIn;
Timeout : integer;
FromLen : integer = SizeOf(From);
Dest_Ip : pointer = nil;
ICMP_Data : pointer = nil;
RecvBuf : pointer = nil;
hp : PHostEnt = nil;
Addr : DWORD = 0;
Seq_No : Word = 0;
sockRaw : TSOCKET;
BRead, Bwrote ,DataSize : integer;
error:integer;


 
Вася Пупкин ©   (2003-09-05 01:14) [3]


procedure fill_icmp_data(icmp_data:pchar; datasize:integer);
var
IcmpHeader:PIcmpHeader;
datapart:pointer;
begin
IcmpHeader := PIcmpHeader(icmp_data);
IcmpHeader^.i_type := ICMP_ECHO;
IcmpHeader^.i_code := 0;
IcmpHeader^.i_id := word(GetCurrentProcessId());
IcmpHeader^.i_cksum := 0;
IcmpHeader^.i_seq := 0;

datapart := icmp_data + sizeof(TIcmpHeader);
FillMemory(datapart, datasize - sizeof(TIcmpHeader),ord("W"));
end;

function checksum( buffer:pword; size: integer):word;
var
cksum : DWORD;
begin
cksum:=0;
while( size > 1 ) do
begin
cksum:=cksum + buffer^;
buffer:=pword(integer(buffer) + sizeof(word));
size :=size-sizeof(word);
end;
if(size<>0 ) then
cksum := cksum + buffer^;
cksum := (cksum shr 16) + (cksum and $ffff);
result:= word(not(cksum + (cksum shr 16)));
end;
procedure decode_resp(buf:pchar;bytes:integer ;var from:TSockAddrIn);
var
IpHeader:PIpHeader;
IcmpHeader:PIcmpHeader;
iphdrlen:word;
begin
IpHeader := PIpHeader(buf);
iphdrlen := (IpHeader^.VerLen and $0F ) * 4 ; // number of 32-bit words *4 = bytes
if (bytes < iphdrlen + ICMP_MIN) then
begin
writeln("Too few bytes from ",inet_ntoa(from.sin_addr));
end;

IcmpHeader := PIcmpHeader(integer(buf) + iphdrlen);

if (IcmpHeader^.i_type <> ICMP_ECHOREPLY) then
begin
writeln("non-echo type %d recvd",IcmpHeader^.i_type);
exit;
end;
if IcmpHeader^.i_id <> word(GetCurrentProcessId()) then
begin
writeln("someone else""s packet!");
exit;
end;
write(Bytes," bytes from ", inet_ntoa(From.sin_addr));
write(" icmp_seq = ",IcmpHeader^.i_seq);
writeln(" time: ",GetTickCount()-IcmpHeader^.timestamp," ms ");
end;



 
Вася Пупкин ©   (2003-09-05 01:15) [4]


begin
TimeOut:=1000;
if (WSAStartup($202,wsaData) <> 0)then
begin
writeln("WSAStartup failed: ",GetLastError());
ExitProcess(STATUS_FAILED);
end;
SockRaw := WSASocket(AF_INET, SOCK_RAW,IPPROTO_ICMP, NIL, 0,WSA_FLAG_OVERLAPPED);
if (sockRaw = INVALID_SOCKET) then
begin
writeln("WSASocket() failed: ",WSAGetLastError());
ExitProcess(STATUS_FAILED);
end;
Bread := setsockopt(SockRaw,SOL_SOCKET,SO_RCVTIMEO,pchar(@Timeout),sizeof(Timeo ut));
if(Bread <> 0) then
begin
writeln("failed to set recv timeout: ",WSAGetLastError());
ExitProcess(STATUS_FAILED);
end;
Bread := setsockopt(SockRaw,SOL_SOCKET,SO_SNDTIMEO,pchar(@Timeout),sizeof(Timeo ut));
if(Bread <> 0) then
begin
writeln("failed to set send timeout: ",WSAGetLastError());
ExitProcess(STATUS_FAILED);
end;
ZeroMemory(@Dest,sizeof(Dest));
hp := gethostbyname(PChar(ParamStr(1)));
Error := GetLastError();
if (Error <> 0) then
begin
writeln("Error in call to gethostbyname().Error code: ",Error);
end;
if (hp = nil ) then Addr := inet_addr(PChar(ParamStr(1)));
if ((hp = nil) and (Addr = INADDR_NONE) ) then
begin
writeln("Unable to resolve ",ParamStr(1));
ExitProcess(STATUS_FAILED);
end;
if (hp <> NIL) then Dest.sin_addr := PInAddr(hp^.h_addr_list^)^
else Dest.sin_addr.s_addr := Addr;
if (hp <> NIL) then Dest.sin_family := hp^.h_addrtype
else Dest.sin_family := AF_INET;
Dest_ip := inet_ntoa(dest.sin_addr);

writeln("Pinging " + hp^.h_name+" ["+ inet_ntoa(dest.sin_addr)+"] ");

datasize := DEF_PACKET_SIZE;

datasize := datasize+sizeof(TIcmpHeader);

GetMem( Icmp_Data, MAX_PACKET);
GetMem(RecvBuf,MAX_PACKET);
if (Icmp_Data = nil) or (RecvBuf = nil) then
begin
writeln("GetMem failed");
ExitProcess(STATUS_FAILED);
end;

ZeroMemory(icmp_data,MAX_PACKET);
ZeroMemory(recvbuf,MAX_PACKET);

fill_icmp_data(Icmp_Data,DataSize);

while(True) do
begin

PIcmpHeader(Icmp_Data)^.i_cksum := 0;
PIcmpHeader(Icmp_Data)^.timestamp := GetTickCount();
PIcmpHeader(Icmp_Data)^.i_seq := Seq_no;
inc(Seq_no);
PIcmpHeader(Icmp_Data)^.i_cksum := checksum(Icmp_Data,DataSize);

Bwrote := sendto(SockRaw,Icmp_Data^,DataSize,0,Dest, sizeof(Dest));
if (Bwrote = SOCKET_ERROR)then
begin
if (WSAGetLastError() = WSAETIMEDOUT) then
begin
writeln("timed out");
continue;
end;
writeln("sendto failed: ",WSAGetLastError());
ExitProcess(STATUS_FAILED);
end;
if (Bwrote < DataSize ) then
begin
writeln("Wrote ",Bwrote, " bytes");
end;
Bread := recvfrom(SockRaw,RecvBuf^,MAX_PACKET,0,TSOCKADDRIN(From),FromLen);
if (Bread = SOCKET_ERROR)then
begin
if (WSAGetLastError() = WSAETIMEDOUT) then
begin
writeln("timed out");
continue;
end;
writeln("recvfrom failed: ",WSAGetLastError());
ExitProcess(STATUS_FAILED);
end;
decode_resp(RecvBuf,Bread,From);
sleep(3000);
end;

WSACleanUp;
FreeMem(RecvBuf);
FreeMem(ICMP_Data);
end.



 
Vladimir   (2003-09-05 11:13) [5]

Можно воспользоваться компонентой IDICMPClient, на вкладке Indy Clients.


 
Reindeer Moss Eater ©   (2003-09-05 11:18) [6]

Идея следующая: прежде чем пытаться соединиться с удаленной машиной - пропинговать ее.

Идея бесполезная и ненужная.

прежде чем пытаться соединиться с удаленной машиной
то есть приложение хочет получить какой-то сервис от удаленного хоста.

пропинговать ее
Для проверки доступности совершенно иного сервиса зачем-то прибегают к помощи сервиса ping.

И что это даст? Допустим требуемый сервис на удаленном хосте отсутствует, а ICMP пакеты к нему проходят. Допустим что нужный сервис на том хосте готов принять наш запрос а ICMP пакеты к нем рубятся его сетевым экраном.
Излишество это и извращение.


 
Е-Моё имя ©   (2003-09-05 11:59) [7]


> Излишество это и извращение.

точна! а фсё от непонимания...


 
RIPSys   (2003-09-05 17:01) [8]

Господа, нужно написать программно пинг, что-бы можна было изменять размер пакета и отслеживать процент потерь, и куда-то это записывать


 
Вася Пупкин ©   (2003-09-05 17:10) [9]

Что мешает ? %)


 
panov ©   (2003-09-05 17:13) [10]

Господа, нужно написать программно пинг, что-бы можна было изменять размер пакета и отслеживать процент потерь, и куда-то это записывать

Конечно нужно.
А вопрос какой?


 
Anatoly Podgoretsky ©   (2003-09-05 17:19) [11]

Вася Пупкин © (05.09.03 17:10) [9]
Неверно, кто запрещает, ему же разрешение нужно.


 
Polevi ©   (2003-09-05 17:49) [12]

ping иногда может быть полезен - некоторые провайдеры (Sky Link) рвут связь после определенного таймаута - ping помогает поддерживать это соединение


 
Anatoly Podgoretsky ©   (2003-09-05 17:56) [13]

Polevi © (05.09.03 17:49) [12]
Не всегда, а вот посылка NOP практически всегда


 
Вася Пупкин ©   (2003-09-05 18:05) [14]

> а кто спорит ? для того и использую -)


 
panov ©   (2003-09-05 18:07) [15]

Вася Пупкин © (05.09.03 18:05) [14]
а кто спорит ? для того и использую -)

Так разрешаем использовать или нет?


 
Е-Моё имя ©   (2003-09-05 18:22) [16]

думаю надо разрешить... а то обидица..


 
panov ©   (2003-09-05 18:26) [17]

>Е-Моё имя © (05.09.03 18:22) [16]
думаю надо разрешить... а то обидица..

Хотя и так тоже может обидеться...

А давайте голосовать?


 
Anatoly Podgoretsky ©   (2003-09-05 19:58) [18]

Делай, разрешаем.

panov © (05.09.03 18:26) [17]
А ты в Потрепаться не бросишь :-)


 
Е-Моё имя ©   (2003-09-05 20:01) [19]


> А давайте голосовать?

давайте!
я буду первым. голосую! да-да-нет-да!


 
SiONYX   (2003-09-05 20:31) [20]

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

Еще раз спасибо всем :)


 
panov ©   (2003-09-05 20:37) [21]

Для решения этой задачи надо использовать сокеты на API, в этом случае можешь сам определить TimeOut.


 
SiONYX   (2003-09-05 21:27) [22]

В догон: в той программе, которую выложил Вася Пупкин, есть ссылка на модуль winsock2, которого у меня нет. Кто-ньть может подсказать, где ее добыть?


 
Anatoly Podgoretsky ©   (2003-09-05 21:44) [23]

Это посторонний модуль, возможно на JEDI есть


 
Oleg The First   (2003-09-13 04:52) [24]

Вот функция которую вызывает у немя пингующий поток.
В Windows не так уж и много потоков можно запустить.
У меня работает 200 потоков паралельно. (можно увеличить до 500)
Значит проблемма состоит с тормозами.
допустим мне нада просканить не 256 адрессов а 40*256 (вот такие у нас сетки)
И что? а то что 256 адрессов сканируется примерно 5 сек
5*40 - долго ждать. ЧТО ДЕЛАТЬ? подскажите!!!!

может не пингами сканить? или как? оч нуна надёжный и быстрый алгоритм.


function IPisLive(HostNorA: String; const TimeOut: Word): Boolean;
var
hIP : THandle;
pBuffer: PChar;
pIpe : ^icmp_echo_reply;
lwsaData: WSAData;
Error : DWORD;
Counter: Word;
// destAddress : In_Addr;
// pHostEn : PHostEnt;
begin
// Создаем handle
hIP := IcmpCreateFile();

Error := WSAStartup(MakeWord(1,1), lwsaData);
if (Error <> 0) then RaiseLastOSError;

GetMem( pIpe, sizeof(icmp_echo_reply) + 32);
GetMem( pBuffer, 32);
pIpe.Data := pBuffer;
pIpe.DataSize := 32;
Result := False;

try
for Counter := 1 to 4 do
begin
IcmpSendEcho(hIP,
Str2IP(HostNorA),
pBuffer,
32,
Nil,
pIpe,
sizeof(icmp_echo_reply) + 32,
TimeOut);

Error := GetLastError();

if (error = 0) then Result := True;
end;
finally
IcmpCloseHandle(hIP);
WSACleanup();
FreeMem(pIpe);
FreeMem(pBuffer);
end;
end;


 
panov ©   (2003-09-13 14:06) [25]

>Oleg The First (13.09.03 04:52) [24]

Свой вопрос - в другой топик.



Страницы: 1 вся ветка

Текущий архив: 2003.11.13;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.047 c
1-41341
Zmei
2003-10-30 18:31
2003.11.13
Параметры


3-40811
Игорь Ч
2003-10-22 13:07
2003.11.13
Компоненты для фильтрации


4-42281
BorH
2003-09-11 03:04
2003.11.13
Создание ярлыка


1-41551
Unknown user
2003-10-27 19:43
2003.11.13
Ошибка при работе функций trunc и int.


3-40994
Term
2003-10-16 12:38
2003.11.13
Как сделать аналог автоинкремнтоного поля в dbf