Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2008.09.14;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




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


2-1217997524
Viod
2008-08-06 08:38
2008.09.14
Обратиться к объекту по имени хранящемся в строке


6-1193124658
Alex_C
2007-10-23 11:30
2008.09.14
Загрузить фаил на сервер


3-1205917843
pavel_guzhanov
2008-03-19 12:10
2008.09.14
rf сделать в запросе два варианта записи в одно поле?


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





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский