Главная страница
    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.51 MB
Время: 0.036 c
7-42160
Fontom
2003-09-02 11:38
2003.11.13
COM порт (Таймауты)


3-41030
KIR
2003-10-14 11:48
2003.11.13
А что если SUM(Table.Field) = null?


3-40814
Feofan
2003-10-22 02:32
2003.11.13
SQL запросы


3-40897
shihovtseva
2003-10-20 09:25
2003.11.13
Ошибка в базе IB


1-41464
E_v_g_e_n_i_y
2003-10-29 08:55
2003.11.13
Операции с файлами





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский