お久しぶりになります。
よろしくお願いします.
現在 192.168.1.1〜192.168.1.254
まで、IndyClient の IdIcmpClient を使用して
デフォルトのタイムアウトを5000(msec) から1000(msec)
に設定してPING処理をしていますが、
接続されていない端末の数にもよると思いますが、
処理が終わるのに 2分40秒ほどかかりました.
そこで、TThread (スレッド)等を使用すると
254台同時にチェック処理するので1秒足らずで処理がおわるのでは
ないのでしょうか?
と思っているのですが、TThread の使用方法がわかりません。
そこで質問ですが、
192.168.1.1〜192.168.1.254に対して
Pingをとばして確認するのにもっとも処理時間を短縮して
なおかつ、精度を下げずに(タイムアウトを1msecにするとかでなく)
処理する方法を教えてください。
目的は、ネットワークに接続されている各PCが
電源が入っているかどうかを確認するプログラムを作成
したいのです。
よろしくお願いします.
こんにちわです。
Indyは少し興味があったのでちょびっとだけテストしてみました。
実際の運用の際はスレッド内を適当にsyncronizeしてあげてください。
テストする際下手な値を入れるとネットワーク管理者に怒られますぞ。
>//-------------------------------------------------------------------------
>//メインフォーム Unit1.pas
>//-------------------------------------------------------------------------
uses に PingThreadを追加
Button1,Edit1,ListBox1
procedure TForm1.Button1Click(Sender: TObject);
var
pthread:array [0..255] of TPingThread;
i:integer;
bufstr:string;
begin
for i:=0 to 20 do //多すぎるとOS止まります
begin
pthread[i]:=TPingThread.Create(True);
pthread[i].IdIcmpClient1:=TIdIcmpClient.Create(self);
bufstr:=Edit1.Text + inttostr(i); //Edit1.text:='***.***.***.'
pthread[i].IdIcmpClient1.Host:=bufstr;
pthread[i].Resume;
end;
>//-------------------------------------------------------------------------
>//スレッド PingThread.pas
>//-------------------------------------------------------------------------
unit PingThread;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ExtCtrls, StdCtrls, IdBaseComponent, IdComponent, IdRawBase, IdRawClient,
IdIcmpClient;
type
TPingThread = class(TThread)
private
{ Private 宣言 }
procedure IdIcmpClient1Reply(ASender: TComponent; const AReplyStatus: TReplyStatus);
public
IdIcmpClient1: TIdIcmpClient;
protected
procedure Execute; override;
end;
implementation
uses Unit1;
{ TPingThread }
procedure TPingThread.Execute;
begin
IdIcmpClient1.OnReply:=IdIcmpClient1Reply;
IdIcmpClient1.Ping;
end;
procedure TPingThread.IdIcmpClient1Reply(ASender: TComponent;
const AReplyStatus: TReplyStatus);
begin
//本当はマズイ
Form1.ListBox1.Items.Add(AReplyStatus.FromIpAddress);
IdIcmpClient1.Free;
end;
end.
>//-------------------------------------------------------------------------
ピーマコ : 「スレッド使うと255台のPCに一気にPING送信出来ると思ったら、ダメですよね〜」
なかざわ : 「使うてるOSはなんやねん?」
オジャマ : 「ピーマコさん、まだWin98なんですよ」
なかざわ : 「それやったらスレッド数は30くらいが限度やな。まぁ、1〜20、21〜40…と分けて実行しても30秒くらいで全部終わるンちゃうか?」
オジャマ : 「わたしのWin2000だったらどうなんですか〜?」
なかざわ : 「聞くよりやってみればエエやん」
オジャマ : 「うわ〜、255個のスレッドでPING送信出来ちゃいました〜 TimeOutが5000msでも5秒くらいで全部応答完了です♪」
ピーマコ : 「でもスレッド使うと応答順序がバラバラですよ〜、送信順にならないですか〜?」
なかざわ : 「ListView使うたら自動ソートのプロパティあるやんか」
ピーマコ : 「あっ、そうですネ…忘れてましたぁ…」
オジャマ : 「VCLってスレッド実行中に使う時は やっぱりSynchronizeでスレッド停止しないとダメなんですか〜? チョット面倒みたいなぁ…」
なかざわ : 「スレッドのOnTerminateイベントで表示せな〜。ンならナンも問題あらへんで」
オジャマ : 「あっ!、そんな手があったんですか〜」
ピーマコ : 「ところで…255個もスレッド使っちゃって、OSはホントに大丈夫なんですか〜?」
なかざわ : 「心配なら、Priority := tpLower; とか追加しといてレベル下げといてや」
ピーマコ : 「ナルホド…、それじゃぁ…ナカザワさんも、そろそろ理想の相手のレベル下げとかないとヤバイですかね〜」
なかざわ : 「ほっとけ!」
スタテツさん、HPW さん
どうもありがとうございます.
当方システムOSはWindows2000です。
プログラムを実行してみました.
結果>>
フォーム上にパネルを254個用意し、
TPanel を配列でせんげんしました。
そして、192.168.1.1〜192.168.1.254 までPingを実行しました。
TPingThreadクラスにTagプロパティを追加して、
以下のように呼び出しました.
for i:=1 to 254 do begin
pthread[i] := TPingThread.Create(True);
pthread[i].Priority := tpLowest;
pthread[i].IdIcmpClient := TIdIcmpClientPing.Create(self);
pthread[i].IdIcmpClient.ReceiveTimeout := 5000;
pthread[i].IdIcmpClient.Host := '192.168.1.' + IntToStr(i);
pthread[i].Tag := i;
pthread[i].Resume;
end;
スレッドユニットでは以下のようにしました。
procedure TPingThread.Execute;
begin
IdIcmpClient.OnReply := IdIcmpClientReply;
IdIcmpClient.Ping;
end;
procedure TPingThread.IdIcmpClientReply(ASender: TComponent; const AReplyStatus: TReplyStatus);
var
S: String;
begin
if AReplyStatus.FromIpAddress = '192.168.1.' + IntToStr(Tag) then begin
Form1.ViewPanel[Tag].Color := clBlue;
end else begin
Form1.ViewPanel[Tag].Color := clRed;
end;
IdIcmpClient.Free;
end;
以上のプログラムを作成してみましたが、
実際 AReplyStatus.FromIpAddress に入ってくるアドレスの値(文字列)が
違っているようで、実際には電源が入っているのに赤くなります。
電源の入っていないものが青くなることはありませんでした.
そこで、Syncronize 等を使用すればいけるのだろうと思いますが、
その方法がわかりません。
どうすればよいのでしょうか?
よろしくお願いします.
ツイート | ![]() |