Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Пинг


Страницы:   1 2 3 4 5

DeeNamid ©   (2008-08-04 12:48:00) 

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

procedure Tping1.Execute;
begin
 while not (terminated or application.Terminated) do begin
//EnterCriticalSection(CS);
 res:=ping_func(ip_addres);
//LeaveCriticalSection(CS);
 synchronize(print_res);
 end;
end;

function Tping1.ping_func(host:string):integer;
var i,failed:integer;
begin
 icmp.ReceiveTimeout:=3000;
 icmp.Host:=host;
 icmp.Ping();
 if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
   ping_func:=icmp.ReplyStatus.MsRoundTripTime
  else
   ping_func:=0;
end;

Когда ставишь критическую секцию результаты отображаются адекватно, но пока один поток пингует все остальные его ждут. Как сделать так что бы все пинговалось независимо друг от друга?


Anatoly Podgoretsky   (2008-08-05 09:30:00) [41]

> Сергей М.  (05.08.2008 9:26:52)  [52]

Поскольку КС защищен сам пинг, то программа сразу становится однопотоковой.


Сергей М.   (2008-08-05 09:26:00) [42]


> DeeNamid ©   (05.08.08 09:12) [50]



> код, он такой синенький.


"Синенький" - это у Slym ©.
В нем не пахнет никакими КС, в отличие от твоего кода.
И не должно пахнуть, ибо КС тут нафих не нужны.


DeeNamid   (2008-08-05 09:19:00) [43]


> Slym

Спасибо тебе, конкретный ответ. Попробую. Только почему через Win API будет работать, как ты говоришь, а с Indy не получается?


DeeNamid   (2008-08-05 09:12:00) [44]


> Сергей М.

Ты помоему вообще не читаешь те темы в которых пишешь. Смотри выше там все написано. Там есть код, он такой синенький.


Slym   (2008-08-05 05:23:00) [45]

 const Host: string;PingCallback:TPingCallback);
begin
 FHost:=Host;
 FPingCallback:=PingCallback;
 inherited Create(CreateSuspended);
end;

procedure TPingThread.DoPingCallback;
begin
 if assigned(FPingCallback) then
   FPingCallback(Self,FHost,FReply);
end;

procedure TPingThread.Execute;
begin
 while not Terminated do
 begin
   FReply:=FormatIcmpEchoReply(IcmpEcho(FHost));
   Synchronize(DoPingCallback);
   Sleep(1000);
 end;
end;

end.

так оно работает:
type
 TForm1 = class(TForm)
   Button1: TButton;
   Memo1: TMemo;
   procedure Button1Click(Sender: TObject);
 private
   procedure PingCallback(Sender:TObject;const Host,Reply:string);
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.PingCallback(Sender: TObject; const Host, Reply: string);
begin
 Memo1.Lines.Add(Host+' = '+Reply);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 TPingThread.Create(false,'192.168.1.1',PingCallback);
 TPingThread.Create(false,'192.168.1.2',PingCallback);
 TPingThread.Create(false,'192.168.1.3',PingCallback);
end;

что еще нада? работу с потоками сам приделай


Slym   (2008-08-05 05:23:00) [46]

накидал за 10!мин:
это было:
unit Icmp;

interface
uses Windows,WinSock,SysUtils;

Const
 IP_SUCCESS = 0;
 IP_STATUS_BASE = 11000;
 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
 PIPOptionInformation=^TIPOptionInformation;
 TIPOptionInformation=packed record
   Ttl:byte;   // Время жизни (используется traceroute-ом)
   Tos:byte;   // Тип обслуживания, обычно 0
   Flags : byte;  // Флаги заголовка IP, обычно 0
   OptionsSize: byte;  // Размер данных в заголовке, обычно 0, максимум 40
   OptionsData: Pointer; // Указатель на данные
 end;

 PIcmpEchoReply=^TIcmpEchoReply;
 TIcmpEchoReply = packed record
   Address:TInAddr;              // Адрес отвечающего
   Status:Longint;               // IP_STATUS (см. ниже)
   RTTime:Longint;              // Время между эхо-запросом и эхо-ответом в миллисекундах
   DataSize:Word;                // Размер возвращенных данных
   Reserved:Word;               // Зарезервировано
   Data:Pointer;               // Указатель на возвращенные данные
   Options:TIPOptionInformation; // Информация из заголовка IP
 end;

 PIcmpEchoReplyEx=^TIcmpEchoReplyEx;
 TIcmpEchoReplyEx = packed record
   IcmpEchoReply:TIcmpEchoReply;
   RawData:array[0..0] of char;
 end;

function IcmpCreateFile:THandle;stdcall;
function IcmpCloseHandle(IcmpHandle:THandle):LongBool;stdcall;
function IcmpSendEcho(IcmpHandle:THandle;DestAddress:Longint;
   RequestData:Pointer;RequestSize:Word;RequestOptns:PIPOptionInformation;
   ReplyBuffer:pointer;ReplySize:DWORD;Timeout:DWORD):Longint;stdcall;

function FormatIcmpEchoReply(IcmpEchoReply:TIcmpEchoReply):string;
function IcmpEcho(const Address:string;TimeOut:integer=3000;Size:word=16):TIcmpEchoReply;

implementation
const IcmpDLL='ICMP.DLL';

resourcestring
 SSuccess='Ответ от %s: число байт=%d время=%dмс TTL=%d';
 STTL_EXPIRED_TRANSIT='Ответ от %s: Превышен срок жизни (TTL) при передаче пакета.';
 SREQ_TIMED_OUT='Превышен интервал ожидания для запроса.';
 SElse='Ответ от %s: код ответа=%d';

function IcmpCreateFile; external IcmpDLL name 'IcmpCreateFile';
function IcmpCloseHandle; external IcmpDLL  name 'IcmpCloseHandle';
function IcmpSendEcho; external IcmpDLL name 'IcmpSendEcho';

function FormatIcmpEchoReply(IcmpEchoReply:TIcmpEchoReply):string;
begin
 case IcmpEchoReply.Status of
   IP_SUCCESS: result:=Format(SSuccess,[StrPas(inet_ntoa(IcmpEchoReply.Address)),IcmpEchoReply. DataSize,IcmpEchoReply.RTTime,IcmpEchoReply.Options.Ttl]);
   IP_REQ_TIMED_OUT: result:=SREQ_TIMED_OUT;
   IP_TTL_EXPIRED_TRANSIT: result:=Format(STTL_EXPIRED_TRANSIT,[StrPas(inet_ntoa(IcmpEchoReply.Address))]);
 else
   result:=Format(SElse,[StrPas(inet_ntoa(IcmpEchoReply.Address)),IcmpEchoReply.Sta tus]);
 end;
end;

function IcmpEcho(const Address:string;TimeOut:integer=3000;Size:word=16):TIcmpEchoReply;
var
 WSAData:TWSAData;
 Host:longint;
 PIerSize:integer;
 PIer:PIcmpEchoReplyEx;
 hIcmp:THandle;
begin
 if WSAStartup(MakeWord(1,1),WSAData)<>0 then RaiseLastOSError;
 try
   Host:=inet_addr(PChar(Address));
   PIerSize:=sizeof(TIcmpEchoReplyEx)+Size;
   GetMem(PIer,PIerSize);
   try
     FillChar(PIer^.RawData,Size,'0');
     PIer^.IcmpEchoReply.Data:=@PIer^.RawData;
     PIer^.IcmpEchoReply.DataSize:=Size;
     hIcmp:=IcmpCreateFile;
     try
       IcmpSendEcho(hIcmp,Host,@PIer^.RawData,Size,Nil,PIer,PIerSize,TimeOut);
       result:=PIer^.IcmpEchoReply;
     finally
       IcmpCloseHandle(hIcmp);
     end;
   finally
     FreeMem(PIer,PIerSize);
   end;
 finally
   WSACleanup();
 end;
end;

end.

это приделал:
unit Unit2;

interface

uses
 Windows,Classes,Icmp;
type
 TPingCallback=procedure(Sender:TObject;const Host,Reply:string) of object;
 TPingThread = class(TThread)
 private
   FHost,FReply:string;
   FPingCallback:TPingCallback;
   procedure DoPingCallback;
 protected
   procedure Execute; override;
 public
   constructor Create(CreateSuspended: Boolean;const Host:string;PingCallback:TPingCallback);
 end;

implementation

{ TPingThread }

constructor TPingThread.Create(CreateSuspended: Boolean;


Сергей М.   (2008-08-04 20:01:00) [47]


> с критическими секциями


Ты уже упарил всех своим "критическими")

Ты ими чтозащищаешь ? Какойресурс ?

Версия Инди, в конце концов, какая ?


DeeNamid   (2008-08-04 18:18:00) [48]

В курсях )) мне под одмином и надо, про файрволл не знаю...
1. Смотри посты, пингует нормально только с критическими секциями, без них пишет полную ерунду.
2. Пробовал бесполезно, пишет ту-же ерунду только медленно.
3. Не понял юмора, ping_func:=0 это означает что превышен интервал ожидания))


Slym   (2008-08-04 18:11:00) [49]

А вы вкурсях что индевая пинга рав сокет юзает? воркает только под одмином и с "открытым" для рав файрволом...
не проще юзать виндовый ICMP.DLL?
по теме:
1. критические секции тут нафег не нужны
2. вы между пингами хоть секунду поспите, а то какаято дос атака получается :)
3. ping_func:=0; - это круто, 10Gbit?


DeeNamid   (2008-08-04 17:49:00) [50]

Пипец какой-то. Делаю так:

function Tping.ping_func(icmp:TIdIcmpClient;host:string):integer;
var i,failed:integer;
   f:textfile;
begin
 icmp.ReceiveTimeout:=3000;
 icmp.Host:=host;
//EnterCriticalSection(CS);
 icmp.Ping();
//LeaveCriticalSection(CS);
 if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
   i:=icmp.ReplyStatus.MsRoundTripTime
  else
   i:=0;
   bite:=icmp.ReplyStatus.BytesReceived;
   assignfile(f,file_name);
   append(f);
   writeln(f,i);
   closefile(f);
end;


Вот файлы: 1-ый
62 62 62 63 62 63 63 62 62 47 63
2-ой
62 62 62 63 62 63 63 62 62
3-ий
62 62 62 63 62 63 63 62 62
4-ый
62 62 62 63 62 63 63 62 62 47
5-ый
78 62 62 63 62 63 63 62 62 47

Я вообще не понимаю откуда эти цифры берутся, нереальные какие-то числа.


DeeNamid   (2008-08-04 17:35:00) [51]

Сейчас попробую.


Dennis I. Komarov   (2008-08-04 17:33:00) [52]

> [40] DeeNamid ©   (04.08.08 17:26)

Проведи следственный эксперимент: Пусть каждый поток пишет все в свой файл. Ни какой визуализации. Уйдешь от синхронизации и крит. секций ...


Сергей М.   (2008-08-04 17:27:00) [53]

Ничего защищать не надо.

Экз-ры IdIcmpClient'ов полностью автономны и никак не влияют на работу друг друга.

Res - это не локальная переменная , а поле объектакласса TPing. Сколько объектов, столько и полей.


DeeNamid   (2008-08-04 17:26:00) [54]


> Medbe}I{onok XML


Харе прикалываться :)) Посмотри на 38 пост, с пингом какие-то замороки.


Medbe}I{onok XML   (2008-08-04 17:25:00) [55]

да причем так хитро искажается, что везде одинаково.


DeeNamid   (2008-08-04 17:25:00) [56]

Точнее даже не так. Посмотри что получается:

function Tping.ping_func(icmp:TIdIcmpClient;host:string):integer;
var i,failed:integer;
begin
 icmp.ReceiveTimeout:=3000;
 icmp.Host:=host;
EnterCriticalSection(CS); //!
 icmp.Ping();
LeaveCriticalSection(CS);//!
 if icmp.ReplyStatus.ReplyStatusType<>rsTimeOut then
   ping_func:=icmp.ReplyStatus.MsRoundTripTime
  else
   ping_func:=0;
end;

Так тоже все работает нормально. Дело в самом пинге. И теперь я вообще ничего не понимаю. Хотя и раньше мало что понимал ))


Medbe}I{onok XML   (2008-08-04 17:24:00) [57]

Я настаиваю на том что после внесения результата в res и до вывода на экран, значение res искажается каким-то другим потоком.

Это точно метапоток из галактик-футбалл.


DeeNamid   (2008-08-04 17:16:00) [58]

Ну ты же видишь разницу в первом случае и во втором? А получилось так просто потому что я всего несколько строк написал, если посмотреть дальше будет видно сходство. Оно и правда не точно идентично, но ведь ясно же что какой-то косяк есть. Я настаиваю на том что после внесения результата в res и до вывода на экран, значение res искажается каким-то другим потоком. И хочу понять почему так происходит? Может есть какие-то другие методы хранения и защиты локальных переменных (кроме threadvar и того как сделано у меня)?


Сергей М.   (2008-08-04 17:08:00) [59]


> memo1 это yandex.ru а остальные наш филиал через vpn


И что ?

Я видижу, что цифирь для Яндекса отличается от цифири для вашей vpn.

А ты утверждал, что цифирь одинакова для любых хостов )


DeeNamid   (2008-08-04 16:54:00) [60]


> Сергей М.


Смотри как интересно получается
memo1:
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 109ms
Время до хоста: 94ms
Время до хоста: 594ms
memo2:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 125ms
Время до хоста: 94ms
Время до хоста: 579ms
memo3:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 125ms
Время до хоста: 94ms
Время до хоста: 579ms
memo4:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 125ms
Время до хоста: 94ms
Время до хоста:579ms
memo5:
Время до хоста: 62ms
Время до хоста: 93ms
Время до хоста: 141ms
Время до хоста: 109ms
Время до хоста: 78ms
Время до хоста: 579ms
Причем memo1 это yandex.ru а остальные наш филиал через vpn.
А вот что будет если внести ping_func в критическую секцию
memo1:
Превышен интервал ожидания
Время до хоста: 1454ms
Время до хоста: 1218ms
Время до хоста: 1469ms
Время до хоста: 1703ms
Время до хоста: 1422ms
memo2:
Время до хоста: 922ms
Время до хоста: 531ms
Время до хоста: 875ms
Превышен интервал ожидания
Время до хоста: 593ms
Время до хоста: 344ms
memo3:
Время до хоста: 93ms
Время до хоста: 125ms
Время до хоста: 171ms
Время до хоста: 110ms
Время до хоста: 297ms
memo4:
Время до хоста: 94ms
Время до хоста: 922ms
Время до хоста: 188ms
Время до хоста: 265ms
Время до хоста: 297ms
Время до хоста: 125ms
memo5:
Время до хоста: 437ms
Превышен интервал ожидания
Время до хоста: 141ms
Время до хоста: 313ms
Время до хоста: 94ms
Время до хоста: 125ms
Другое дело правда?


Страницы:   1 2 3 4 5

Наверх

Титульная страница Поиск, карта сайта Написать письмо