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

Вниз

Пинг   Найти похожие ветки 

 
DeeNamid ©   (2008-08-04 12:48) [0]

Вопрос такой, делаю пять потоков которые пингуют каждый свою машину и выводять результаты на пять окон, проблема с 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;

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


 
Сергей М. ©   (2008-08-04 12:53) [1]


> Как сделать так что бы все пинговалось независимо друг от
> друга?
>


Каждый поток должен создавать и юзать свой собственный экз-р класса TIdICMP.


 
DeeNamid ©   (2008-08-04 12:54) [2]

Так и сделано вот полный вид execut"a

procedure Tping1.Execute;
var b:boolean;i:integer;
begin
 FreeOnTerminate:=true;
 b:=true;
 icmp:=TIdIcmpClient.Create(nil);
 while not (terminated or application.Terminated) do begin
EnterCriticalSection(CS);
 res:=ping_func(ip_addres);
LeaveCriticalSection(CS);
 synchronize(print_res);
 end;
 icmp.Destroy;
end;


 
DeeNamid ©   (2008-08-04 12:55) [3]

Так и сделано вот полный вид execut"a

procedure Tping1.Execute;
var b:boolean;i:integer;
begin
 FreeOnTerminate:=true;
 b:=true;
 icmp:=TIdIcmpClient.Create(nil);
 while not (terminated or application.Terminated) do begin
EnterCriticalSection(CS);
 res:=ping_func(ip_addres);
LeaveCriticalSection(CS);
 synchronize(print_res);
 end;
 icmp.Destroy;
end;


 
Сергей М. ©   (2008-08-04 12:58) [4]


> Так и сделано


Нет, сделано не так.

Создавать-то ты создаешь по экземпляру на каждый поток, а юзаешь в каждом потоке один и то же экз-р.


 
DeeNamid ©   (2008-08-04 13:02) [5]

Недопонял. Как юзать разные экземпляры?


 
Сергей М. ©   (2008-08-04 13:04) [6]

function Tping1.ping_func(ICMP: TIdICMP; 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;

procedure Tping1.Execute;
var
  ICMPInstance: TIdICMP;
begin
..
ICMPInstance:=TIdIcmpClient.Create(nil);
try
  while not (terminated or application.Terminated) do begin
    res:=ping_func(ICMPInstance, ip_addres);
    synchronize(print_res);
  end;
finally
  ICMPInstance.Free;
end;
..
end;


 
antonn ©   (2008-08-04 13:20) [7]

Ого, Сергей показал готовый код, где то здесь подвох! %)


 
Сергей М. ©   (2008-08-04 13:42) [8]


> antonn ©   (04.08.08 13:20) [7]


Подвох не у меня , а у автора - область видимости ид-ра icmp он не удосужился уточнить)


 
Anatoly Podgoretsky ©   (2008-08-04 13:59) [9]

Да он вообще мало информации предоставил, зато он предоставил нам возможность проявиться телепатические способности.


 
DeeNamid ©   (2008-08-04 14:22) [10]

Ну смотрите тады ))
Главная форма:

type
 TForm1 = class(TForm)
   Memo1: TMemo;
   Button1: TButton;
   ComboBox1: TComboBox;
   Panel1: TPanel;
   Label7: TLabel;
   Label8: TLabel;
   Label9: TLabel;
   Label10: TLabel;
   Label11: TLabel;
   Label12: TLabel;
   Memo2: TMemo;
   Memo3: TMemo;
   Memo4: TMemo;
   Memo5: TMemo;
   Memo6: TMemo;
   Button2: TButton;
   procedure Button1Click(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure Button2Click(Sender: TObject);
   procedure FormClose(Sender: TObject; var Action: TCloseAction);
 private
   ping1,ping2,ping3,ping4,ping5: Tping;
   { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

procedure TForm1.Button1Click(Sender: TObject);
begin
ping1:=Tping.Create("93.158.134.3",1);
ping2:=Tping.Create("172.21.161.34",2);
ping3:=Tping.Create("172.21.61.44",3);
ping4:=Tping.Create("10.61.1.126",4);
ping5:=Tping.Create("172.21.61.46",5);
 ping1.Resume;
 ping2.Resume;
 ping3.Resume;
 ping4.Resume;
 ping5.Resume;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
try
  ping1.Terminate;
  ping2.Terminate;
  ping3.Terminate;
  ping4.Terminate;
  ping5.Terminate;
except
end;
end;

Unit2:

type
 Tping = class(TThread)
 private
   memo_num:integer;ip_addres:string;
   res:integer;res_str:string;
 protected
   procedure Execute; override;
   function ping_func(icmp:TIdIcmpClient;host:string):integer;
   procedure print_res;
 public
   constructor create(ip_addr:string;i:integer);
 end;
var CS:TRTLCriticalSection;
implementation
uses Unit1;

function Tping.ping_func(icmp:TIdIcmpClient;host:string):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;

procedure Tping.Execute;
var icmp: TIdIcmpClient;
begin
 FreeOnTerminate:=true;
 icmp:=TIdIcmpClient.Create(nil);
 while not (terminated or application.Terminated) do begin
//EnterCriticalSection(CS);
 res:=ping_func(icmp,ip_addres);//мне кажется здесь заморочка с res
//LeaveCriticalSection(CS);
 sleep(0);
 synchronize(print_res);
 end;
 icmp.Destroy;
end;

procedure Tping.print_res;
begin
if res>0 then res_str:="&#194;&#240;&#229;&#236;&#255; &#228;&#238; &#245;&#238;&#241;&#242;&#224;: "+inttostr(res)+"ms" else res_str:="&#207;&#240;&#229;&#226;&#251;&#248;&#229;&#237; &#232;&#237;&#242;&#229;&#240;&#226;&#224;&#235; &#238;&#230;&#232;&#228;&#224;&#237;&#232;&#255;";
case memo_num of
 1: Form1.memo2.Lines.add(res_str);
 2: Form1.memo3.Lines.add(res_str);
 3: Form1.memo4.Lines.add(res_str);
 4: Form1.memo5.Lines.add(res_str);
 5: Form1.memo6.Lines.add(res_str);
end;
Form1.memo1.lines.add("&#207;&#238;&#242;&#238;&#234; &#237;&#238;&#236;&#229;&#240;: "+inttostr(memo_num));
Form1.Memo1.Lines.Add(res_str);
end;

constructor Tping.create(ip_addr: string;i:integer);
begin
ip_addres:=ip_addr;
memo_num:=i;
inherited create(true);
end;

initialization
 InitializeCriticalSection(CS);
end.

Как-то так. Сделал как ты сказал, ничего не изменилось.


 
Dennis I. Komarov ©   (2008-08-04 14:25) [11]

> [7] antonn ©   (04.08.08 13:20)

Значок видишь?


 
DeeNamid ©   (2008-08-04 14:31) [12]

Ты о чем?


 
DeeNamid ©   (2008-08-04 14:58) [13]

Куда-то все пропали... Помогите прояснить проблему. Почему не получается сделать так что-бы пять потоков независимо друг от друга корректно работали.


 
Сергей М. ©   (2008-08-04 15:47) [14]


> DeeNamid ©   (04.08.08 14:58) [13]


А в чем, по-твоему, выражается их "зависимость друг от друга", в данный момент, т.е. при реализации, приведенной тобой в [10] ?


 
DeeNamid ©   (2008-08-04 16:01) [15]

Зависимость заключается в том что все пять потоков выводят на экран одни и те же значения.
Есть пять потоков и пять компонентов memo, на которые должны выводиться результаты пинга. Если использовать критическую секцию то все происходит нормально, то есть в каждом окошке отображаются корректные результаты. Но в этом случае пока пингует один поток, остальные его ждут, а это не гуд. Если же закомментировать эту секцию, то происходит следующее - все окошки отображают одни и те же цифры, при чем при отладке в watch"е видно что в процедуре print_res сам res для всех потоков имеет одинаковое значение. Вот в этом и вопрос - почему так происходит что res открыт для всех потоков, если он является локальной переменной класа TPing?


 
Сергей М. ©   (2008-08-04 16:13) [16]


> res для всех потоков имеет одинаковое значение


Какое конкретно ?


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

Ну к примеру 154, тогда на вывод получается:
Время до хоста: 154 ms
и так пять раз на все окна.


 
Medbe}I{onok XML ©   (2008-08-04 16:22) [18]

результат пинга число?

убрать всю эту ахинею. после окончания пинга и получения результата посылать главному окну сообщение, результат передавать в WParam или LParam


 
DeeNamid ©   (2008-08-04 16:25) [19]

Что-то как-то ты категорично вещаешь. Объясни подробнее плиз что такое

> результат передавать в WParam или LParam?


 
Сергей М. ©   (2008-08-04 16:25) [20]

А ты вообще понимаешь, что означает и как вычисляется св-во MsRoundTripTime ?

Оно никаким боком не относится к "время до хоста".


 
DeeNamid ©   (2008-08-04 16:27) [21]

Ладно это не важно, мне надо понять в чем проблема, почему локальную переменную имеют все подряд?


 
Medbe}I{onok XML ©   (2008-08-04 16:28) [22]

procedure Tping.Execute;
var icmp: TIdIcmpClient;
begin
FreeOnTerminate:=true; //Это в конструктор убрать
icmp:=TIdIcmpClient.Create(nil);
while not (terminated or application.Terminated) do begin
res:=ping_func(icmp,ip_addres);
end;
icmp.Destroy;
PostMessage(fMainFormHandle,WM_MYPING_MSG,<fNumberForMemo>,LParam(res));
end;


 
Medbe}I{onok XML ©   (2008-08-04 16:29) [23]

fMainFormHandle (хендл окна с лежащим не ём мемом) и fNumberForMemo (в каком мемо рисовать результат) передавать конструктору вторичного потока.


 
Medbe}I{onok XML ©   (2008-08-04 16:31) [24]

Точнее так, если там надо пинговать пока рак не свистнет:

procedure Tping.Execute;
var icmp: TIdIcmpClient;
begin
FreeOnTerminate:=true; //Это в конструктор убрать
icmp:=TIdIcmpClient.Create(nil);
while not (terminated or application.Terminated) do begin
res:=ping_func(icmp,ip_addres);
PostMessage(fMainFormHandle,WM_MYPING_MSG,<fNumberForMemo>,LParam
end;
icmp.Destroy;
(res));
end;


 
Сергей М. ©   (2008-08-04 16:32) [25]


> почему локальную переменную имеют все подряд?


Никто ее не "имеет")

С логикой в твоем коде все более-менее в порядке.

Пробуй пинговать хосты из разных концов Тырнета - получишь разные результаты.


 
DeeNamid ©   (2008-08-04 16:33) [26]

То есть,
constructor Tping.create(ip_addr: string;i:integer;fMainFormHandle;fNumberForMemo);
так? Номер мемо просто цифра? И где взять хендл ?


 
Medbe}I{onok XML ©   (2008-08-04 16:36) [27]

constructor Tping.create(ip_addr: string;fMainFormHandle : HWND;fNumberForMemo : integer);


 
Medbe}I{onok XML ©   (2008-08-04 16:38) [28]

procedure TForm1.Button1Click(Sender: TObject);
begin

ping1:=Tping.Create("93.158.134.3",Handle,1);
ping2:=Tping.Create("172.21.161.34",Handle,2);
ping3:=Tping.Create("172.21.61.44",,Handle,3);
ping4:=Tping.Create("10.61.1.126",Handle,4);
ping5:=Tping.Create("172.21.61.46",Handle,5);


 
Сергей М. ©   (2008-08-04 16:41) [29]


> Medbe}I{onok XML ©   (04.08.08 16:38) [28]


Ну и какая нафих разница ? Что, от вида синхронизации зависит трип-тайм ?)


 
Medbe}I{onok XML ©   (2008-08-04 16:41) [30]

я его спасаю от ужасов print_res


 
Сергей М. ©   (2008-08-04 16:43) [31]


> спасаю от ужасов print_res
>


На якобы имеющее место "проблему" эти "ужасы" никак не влияют)


 
Medbe}I{onok XML ©   (2008-08-04 16:44) [32]

к тому же будет побочный положительный эффект:
нитка и главная форма потеряют имеющуюся чудовищную взаимозависимость между собой и отлаживать все станет проще.


 
Medbe}I{onok XML ©   (2008-08-04 16:45) [33]

На якобы имеющее место "проблему" эти "ужасы" никак не влияют)

Влияют на скорость понимания что они и правда не влияют.
:)


 
DeeNamid ©   (2008-08-04 16:54) [34]


> Сергей М.


Смотри как интересно получается
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
Другое дело правда?


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


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


И что ?

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

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


 
DeeNamid ©   (2008-08-04 17:16) [36]

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


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

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

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


 
DeeNamid ©   (2008-08-04 17:25) [38]

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

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:25) [39]

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


 
DeeNamid ©   (2008-08-04 17:26) [40]


> Medbe}I{onok XML


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


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

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

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

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


 
Dennis I. Komarov ©   (2008-08-04 17:33) [42]

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

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


 
DeeNamid ©   (2008-08-04 17:35) [43]

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


 
DeeNamid ©   (2008-08-04 17:49) [44]

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

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

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


 
Slym ©   (2008-08-04 18:11) [45]

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


 
DeeNamid ©   (2008-08-04 18:18) [46]

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


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


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


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

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

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


 
Slym ©   (2008-08-05 05:23) [48]

накидал за 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;


 
Slym ©   (2008-08-05 05:23) [49]

 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;

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


 
DeeNamid ©   (2008-08-05 09:12) [50]


> Сергей М.

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


 
DeeNamid ©   (2008-08-05 09:19) [51]


> Slym

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


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


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



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


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


 
Anatoly Podgoretsky ©   (2008-08-05 09:30) [53]

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

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


 
DeeNamid ©   (2008-08-05 09:47) [54]


> Anatoly Podgoretsky

Ну да, вот тут и проблема, а если не защищать то получается ерунда


 
Anatoly Podgoretsky ©   (2008-08-05 09:52) [55]

> DeeNamid  (05.08.2008 9:47:54)  [54]

Так у тебя ошибки в реализации, потому и ерунда.


 
DeeNamid ©   (2008-08-05 09:59) [56]


> Anatoly Podgoretsky


Покажи где. Два дня прошу людей - покажите мне мои ошибки.


 
Anatoly Podgoretsky ©   (2008-08-05 10:08) [57]

А всем лень в таком коде разбираться. Слишком много телепатии надо применять.


 
DeeNamid ©   (2008-08-05 10:25) [58]


> Anatoly Podgoretsky

Елки-палки, да что там разбираться, 40 строк кода. Посмотри на 10-ый пост, там весь код написан.


 
Anatoly Podgoretsky ©   (2008-08-05 10:28) [59]

> DeeNamid  (05.08.2008 10:25:58)  [58]

А нафига мне столько раз смотреть?
Проси кого ни будь другого, кому не лень много раз смотреть.


 
DeeNamid ©   (2008-08-05 10:39) [60]


> Anatoly Podgoretsky

А кому не лень? И зачем ты тогда говоришь что у меня ошибки в реализации, если не можешь на эти ошибки указать?


 
Сергей М. ©   (2008-08-05 11:02) [61]


> Anatoly Podgoretsky ©   (05.08.08 09:30) [53]


Ты имеешь ввиду КС в потрохах самОй IcmpSendEcho ?


 
Сергей М. ©   (2008-08-05 11:11) [62]


> покажите мне мои ошибки


Ты не учитываешь вот это:

SequenceID is a Word value used as a packet identifier for the Ping request. SequenceID is also used when decoding the response packets for a Ping request. When SequenceID contains a non-zero value, it is used to match an echo response to the original ping request with the same sequence identifer. SequenceID can be set to a unique value to identify a specific Ping request and/or response

Copyright © 1993-2006, Chad Z. Hower (aka Kudzu) and the Indy Pit Crew. All rights reserved.


 
Anatoly Podgoretsky ©   (2008-08-05 11:12) [63]

> DeeNamid  (05.08.2008 10:39:00)  [60]

Потому что у тебя программа не работает.
И с чего ты взял, что не могу, ты не путай не хочу с не могу.


 
Anatoly Podgoretsky ©   (2008-08-05 11:13) [64]

> Сергей М.  (05.08.2008 11:02:01)  [61]

Не из его кода

EnterCriticalSection(CS);
res:=ping_func(ip_addres);
LeaveCriticalSection(CS);

Вот это убивает многопоточность.


 
Сергей М. ©   (2008-08-05 11:16) [65]


> Anatoly Podgoretsky ©   (05.08.08 11:13) [64]


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


 
Anatoly Podgoretsky ©   (2008-08-05 11:32) [66]

> Сергей М.  (05.08.2008 11:16:05)  [65]

Так считать не надо, он пишет, что если он раскомментирует эти строки, то у него почему то исчезает многопоточность. А когда комментирует, то у него возникает проблема с порчей переменных.


 
DeeNamid ©   (2008-08-05 11:36) [67]


> Anatoly Podgoretsky ©   (05.08.08 11:32) [66]

Все ты правильно говоришь.

А скажите мне такую вещь
icmp:=TIdIcmpClient.Create(nil);
здесь ведь наверно надо указать создателя компонента icmp?


 
Сергей М. ©   (2008-08-05 11:40) [68]


> у него почему то исчезает многопоточность


Нет, он понимает, почему она исчезает.
Но не понимает, что icmp-запросы требуют уникальной идентификации секвенций.
В случае с IcmpSendEcho это требование, по всей видимости, обеспечивается неявно, в случае с индейскими ро-сокетами это нужно делать явно.


 
Medbe}I{onok XML ©   (2008-08-05 11:40) [69]

создатель - это ты


 
Dennis I. Komarov ©   (2008-08-05 11:41) [70]

> [67] DeeNamid ©   (05.08.08 11:36)

для чего?


 
Anatoly Podgoretsky ©   (2008-08-05 11:42) [71]

> DeeNamid  (05.08.2008 11:36:07)  [67]

Не обязательно, можно и nil, ведь все зависит от того, кто будет уничтожать компонент, будет ли где либо использоваться значение Owner.

Лично я так никогда не делаю, только Self, разумеется не по отношению к TIdIcmpClient, а ко всем компонентам.


 
Сергей М. ©   (2008-08-05 11:45) [72]


> здесь ведь наверно надо указать создателя компонента


На суть "проблемы" это никак не влияет.


 
Anatoly Podgoretsky ©   (2008-08-05 11:47) [73]

> Сергей М.  (05.08.2008 11:40:08)  [68]

Я на индейцах давно поставил очень большой крест. А нас разные пути, я по своей дороге иду, а индейцы по своей. И разбираться с ихним монстром и конкретными функциями у меня нет никакого желания, тем более, что чем дальше, тем больше монстр становится. Кажется уже и авторы сами не понимают, как это вообще работает.


 
DeeNamid ©   (2008-08-05 11:49) [74]


> Сергей М. ©   (05.08.08 11:40) [68]
> icmp-запросы требуют уникальной идентификации секвенций.

от есть я пишу так: icmp.Ping("",0); где вместо 0 я должен ставить уникальный идентификатор? какой?


 
DeeNamid ©   (2008-08-05 11:51) [75]


> Anatoly Podgoretsky ©   (05.08.08 11:47) [73]

и это говорит человек который переводил "IndyInDepth". :D
Что советуешь, использовать WinAPI или что-то другое?


 
Medbe}I{onok XML ©   (2008-08-05 11:54) [76]

и это говорит человек который переводил "IndyInDepth". :D

Там по ходу промпт поработал.


 
Сергей М. ©   (2008-08-05 11:58) [77]


> какой?


Генератор уникальных идентификаторов секвенций нужно реализовать.

Вот его-то в условиях много поточности как раз и следует защитить КС)

А защита метода Ping() как такового нафиг не нужна)


 
DeeNamid ©   (2008-08-05 12:03) [78]


> Сергей М. ©   (05.08.08 11:58) [77]

Что-то как-то сложновато ты высказался. уникальных идентификаторов секвенций это как сделать? я сейчас попробовал сделать icmp.Ping("",i);, где i - номер потока. Получились немного другие результаты, но все равно чушь. Например он явно неработающий IP-шник пинговал как работающий.


 
Сергей М. ©   (2008-08-05 12:06) [79]


> где i - номер потока


Да не номер потока, а уникальный номер запроса !

Вот для этого и нужен генератор)


 
Сергей М. ©   (2008-08-05 12:07) [80]

Секвенция - это дейтаграмма запроса и ответная дейтаграмма на этот запрос.


 
Сергей М. ©   (2008-08-05 12:12) [81]


> DeeNamid ©   (05.08.08 12:03) [78]


Бросай тренироваться на своей vpn, используй для тестирования хосты реальных сетей, желательно с разными маршрутами)


 
DeeNamid ©   (2008-08-05 12:22) [82]

Я понял. То есть - я делаю генератор номера запроса, ставлю его в пинг. icmp сам по номеру запроса определяет номер ответа и пишет мне что он красавчег.
Хорошо сделаю реальные адреса, хотя я и использовал yandex.ru для пинга.


 
Сергей М. ©   (2008-08-05 12:23) [83]


> DeeNamid ©   (05.08.08 12:03) [78]


Первым делом при анализе результата запроса ты должен сравнить ReplyStatus.SequenceId c тем который ты передал параметром при вызове метода Ping.

Если они не совпадают, то ReplyStatus отражает контент ответа на совсем другой запрос)


 
Сергей М. ©   (2008-08-05 12:24) [84]

И вообще - используй событие OnReply.


 
Anatoly Podgoretsky ©   (2008-08-05 13:08) [85]

> DeeNamid  (05.08.2008 11:51:15)  [75]

Странный вывод, что я не могу перевести и не использовать одновременно.
А переводил для вас и для себя, что бы понять, что зто за рыба.

Порекоменду

1. WinAPI, если это единственная задача;
2. Sinapse;
3. ICS;
4. поискать на Торри отдельный компонент, только для этой задачи.


 
Anatoly Podgoretsky ©   (2008-08-05 13:08) [86]

> Medbe}I{onok XML  (05.08.2008 11:54:16)  [76]

Этот Промпт Я


 
DeeNamid ©   (2008-08-05 13:09) [87]


> И вообще - используй событие OnReply.

В смысле создать событие, которое будет отслеживать получение ответа, и в нем уже проверять ReplyStatus.SequenceId


 
Сергей М. ©   (2008-08-05 13:11) [88]


> DeeNamid ©   (05.08.08 13:09) [87]


Да, в этом смысле, хотя и не обязательно (но очевидно. если такое событие фигурирует у компонента).


 
DeeNamid ©   (2008-08-05 13:15) [89]


> Anatoly Podgoretsky ©   (05.08.08 13:08) [85]


Скачал Internet Component Suite, там есть отдельный компонент пинг, для него есть какой-то хелп или описание?


 
Сергей М. ©   (2008-08-05 13:25) [90]


> Скачал Internet Component Suite


Мог бы и не качать)

Тоже самое, но с видом в анфас, тебе продемонстрировал Slym (C) - ICS.TPing использует именно API-вызов


 
Anatoly Podgoretsky ©   (2008-08-05 13:39) [91]

> DeeNamid  (05.08.2008 13:15:29)  [89]

С хелпами для открытых, бесплатных программ всегда было плоховато. Но есть много примеров, wiki, FAQ и не полная справка. Ориентируйся в основном на примеры.


 
Сергей М. ©   (2008-08-05 13:43) [92]


> DeeNamid ©   (05.08.08 13:15) [89]


Взяв на вооружение ICS забудь про кросплатформенность своего приложения - оно не будет работать нигде кроме как под виндой


 
DeeNamid ©   (2008-08-05 13:45) [93]

Спасибо всем. Начну разбираться с API и с ICS, потом отпишу что получилось.



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

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

Наверх




Память: 0.74 MB
Время: 0.029 c
15-1216787659
Тоша
2008-07-23 08:34
2008.09.14
Социологический опрос


2-1217104217
++vist++
2008-07-27 00:30
2008.09.14
Как считать коды яркостей RGB


15-1216990440
Ruzzz
2008-07-25 16:54
2008.09.14
Delphi - это он, она или оно?


2-1217799907
demon
2008-08-04 01:45
2008.09.14
RegisterClass и RegisterClassEx в чем разница?


11-1192822029
Вячеслав
2007-10-19 23:27
2008.09.14
Высоту списка в ComboBox?