IdTcpserver向掉线的Idtcpclient发送消息,捉不到异常?(100分)

  • 主题发起人 主题发起人 liuchong
  • 开始时间 开始时间
L

liuchong

Unregistered / Unconfirmed
GUEST, unregistred user!
procedure TForm1.IdTCPServer1Execute(AThread: TIdPeerThread);
var
B:Byte;
I:Cardinal;
begin
AThread.Connection.ReadBuffer(B,SizeOf(B));
try
for I:=0 to IdTCPServer1.Threads.LockList.Count-1 do
begin
try
TIdPeerThread(IdTCPServer1.Threads.LockList.Items).Connection.WriteBuffer(B,SizeOf(B));
IdTCPServer1.Threads.UnlockList;
except
TIdPeerThread(IdTCPServer1.Threads.LockList.Items).Stop;
TIdPeerThread(IdTCPServer1.Threads.LockList.Items).Free;
end;
end;
finally
IdTCPServer1.Threads.UnlockList;
end;
end;

在Idtcpclient被拔掉网线的时候,上面的代码捉不到异常,如何解决?

另一个问题:
想处理单击“最小化”按钮和单击任务栏使窗口最小化,下面的代码怎样改写?
procedure WMSysCommand(var Msg:TMessage);message WM_SYSCOMMAND;
procedure TForm1.WMSysCommand(var Msg:TMessage);
begin
if (Msg.WParam = SC_MINIMIZE) then
CoolTrayIcon1.HideMainForm
else
inherited;
end;
 
可以用类似PING之类的程序检测是否Idtcpclient在线:
Delphi编程实现Ping操作

  张泰立

  使用过网络的用户都熟悉“Ping”这个指令,它是一个DOS下的可执行文件,一般用
它来检查网络连接的好坏程度。其基本原理是利用TCP/IP协议包中ICMP协议中的一个功
能,即向所指定的计算机发送一个请求,收到请求的计算机返回一个应答,借此来判断该
计算机是否在网上运行或者检查网络连接是否稳定可靠。在Ping程序执行过程中,双方
计算机所耗费的资源都很少,因此,它是一个非常实用的工具。


  我们可以通过编程来实现“Ping”操作,对其加以改进,使之具有Windows的界面
风格,显示比DOS更加直观。

  首先,对编程中需要的动态链接库作一简要说明:在Windows的System目录下,你
可以找到Icmp.dll文件,该动态链接库提供了ICMP协议的所有功能,我们的编程就建立


  对该动态链接库的调用上。

  Icmp.dll文件内的调用函数说明如下:

  1、IcmpCreateFile

  打开一个句柄,通过该句柄你可以发送ICMP的请求回送报文。

  2、IcmpCloseHandle

  关闭你通过IcmpCreateFile函数打开的句柄。

  3、IcmpSendEcho

  通过你打开的句柄发送ICMP请求,在超时或应答报文接收后返回。其参数基本上和
它的帧结构一致,可参看下面的程序部分,其具体含意你可以参看有关ICMP协议的书
籍。

  初步了解了上述的三个函数后,我们就可以开始编程了。

  首先,我们的程序运行后应该有如图1所示的基本功能。为此,我们可先在Delphi的
窗口中放入右上图中所示的控件,如按钮、编辑框和文本显示框等。

  (G72.JPG)

  例程运行示意图

  然后,在程序的开始部分(FormCreate)对WinSocket进行初始化,其作用是申明
使用的版本信息,同时调入Icmp.dll库。

  type

   PIPOptionInformation = ^TIPOptionInformation;

   TIPOptionInformation = packed record

   TTL: Byte;

   TOS: Byte;

   Flags: Byte;

   OptionsSize: Byte;

   OptionsData: PChar;

   end;

   PIcmpEchoReply = ^TIcmpEchoReply;

   TIcmpEchoReply = packed record

   Address: DWORD;

   Status: DWORD;

   RTT: DWORD;

   DataSize: Word;

   Reserved: Word;

   Data: Pointer;

   Options: TIPOptionInformation;

   end;

   TIcmpCreateFile = function: THandle; stdcall;

   TIcmpCloseHandle = function(IcmpHandle: THandle): Boolean;
stdcall;

   TIcmpSendEcho = function(IcmpHandle:THandle;

   DestinationAddress: DWORD;

   RequestData: Pointer;

   RequestSize: Word;

   RequestOptions: PIPOptionInformation;

   ReplyBuffer: Pointer;

   ReplySize: DWord;

   Timeout: DWord

   ): DWord; stdcall;

   TMyPing = class(TForm)

   Panel1: TPanel;

   Label1: TLabel;

   PingEdit: TEdit;

   ExeBtn: TButton;

   Button2: TButton;

   Button3: TButton;

   StatusShow: TMemo;

   procedure Button3Click(Sender: TObject);

   procedure FormCreate(Sender: TObject);

   procedure ExeBtnClick(Sender: TObject);

   private

   { Private declarations }

   hICMP: THANDLE;

   IcmpCreateFile : TIcmpCreateFile;

   IcmpCloseHandle: TIcmpCloseHandle;

   IcmpSendEcho: TIcmpSendEcho;

   public

   { Public declarations }

  end;

  procedure TMyPing.FormCreate(Sender: TObject);

  var

   WSAData: TWSAData;

   hICMPdll: HMODULE;

  begin

?
   // Load the icmp.dll stuff

   hICMPdll := LoadLibrary('icmp.dll');

   @ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile');

   @IcmpCloseHandle := GetProcAddress(hICMPdll,
'IcmpCloseHandle');

   @IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');

   hICMP := IcmpCreateFile;

   StatusShow.Text := '';

   StatusShow.Lines.Add('目的IP地址 字节数 返回时间(毫秒)');

  end;

  接下来,就要进行如下所示的Ping操作的实际编程过程了。

  procedure TMyPing.ExeBtnClick(Sender: TObject);

  var

   IPOpt:TIPOptionInformation;// IP Options for packet to send

   FIPAddress:DWORD;

   pReqData,pRevData:PChar;

   pIPE:PIcmpEchoReply;// ICMP Echo reply buffer

   FSize: DWORD;

   MyString:string;

   FTimeOut:DWORD;

   BufferSize:DWORD;

  begin

   if PingEdit.Text <> '' then

   begin

   FIPAddress := inet_addr(PChar(PingEdit.Text));

   FSize := 40;

   BufferSize := SizeOf(TICMPEchoReply) + FSize;

   GetMem(pRevData,FSize);

   GetMem(pIPE,BufferSize);

   FillChar(pIPE^, SizeOf(pIPE^), 0);

   pIPE^.Data := pRevData;

   MyString := 'Hello,World';

   pReqData := PChar(MyString);

   FillChar(IPOpt, Sizeof(IPOpt), 0);

   IPOpt.TTL := 64;

   FTimeOut := 4000;

   IcmpSendEcho(hICMP, FIPAddress, pReqData, Length(MyString),
@IPOpt, pIPE, BufferSize, FTimeOut);

   if pReqData^ = pIPE^.Options.OptionsData^ then

   begin

   StatusShow.Lines.Add(PChar(PingEdit.Text) + ' '
+IntToStr(pIPE^.DataSize) + ' ' +IntToStr(pIPE^.RTT));

   end;

   begin

   StatusShow.Lines.Add(PChar(PingEdit.Text) + ' '
+IntToStr(pIPE^.DataSize) + ' ' +IntToStr(pIPE^.RTT));

   end;

   FreeMem(pRevData);

   FreeMem(pIPE);

   end

  end;

  通过上面的编程,我们就实现了Ping功能的界面操作。实际上,ICMP协议的功能还
有很

  多,都可以通过对Icmp.dll的函数调用来实现。
------------------------------------------------
问题: 如何在Delphi代码中隐式运行ping命令,并返加 ( 积分: 100 )
分类: 非技术问题

来自: coao, 时间: 2000-04-05 9:39:33, ID: 212797


来自: www, 时间: 2000-04-05 9:46:58, ID: 212804

winexec('ping ...>aa.txt',sw_hide);
然后读取aa.txt

来自: 程旭, 时间: 2000-04-05 10:04:17, ID: 212826
可以用ICMP,你需要的活我可以给你M资料。

来自: Big_Z, 时间: 2000-04-05 11:05:47, ID: 212883
程旭兄,Mail 一个给我吧,先谢了!^_^!
big_z_@21cn.com


来自: SuperMMX, 时间: 2000-04-05 12:46:23, ID: 212962
简单的就用3w的,要保险点的有一个函数叫 createProcessAndWait
在这里找一下吧,都要用文件。

来自: g622, 时间: 2000-04-05 12:54:18, ID: 212978
www的最简单.

来自: Big_Z, 时间: 2000-04-05 13:09:13, ID: 212998
www的简单,
但怎么知道 Ping 完了呢,if “aa.txt” 已经存在?
建议还是不要偷懒,调用进程 Ping

来自: Flintstone, 时间: 2000-04-05 16:08:34, ID: 213102
可以用ics控件包中的ping控件,这个控件比较好的实现了ping的功能。

来自: wrench, 时间: 2000-04-05 17:05:04, ID: 213135
用进程执行Ping并等待


来自: codeguru, 时间: 2000-04-05 19:15:38, ID: 213194
程旭兄,呵呵,麻烦mail一个给我吧,谢谢
blackbull@21cn.com

来自: CaiFeng, 时间: 2000-04-05 20:26:06, ID: 213225
运用系统的重定向和管道技术可以隐藏的Dos控制台
SECURITY_ATTRIBUTES lsa
STARTUPINFO si
通过设置si.wShowWindow=SW_HIDE,可以使得DOS程序在执行时不显示出来

来自: Pipi., 时间: 2000-04-06 0:20:46, ID: 213451
ics 的 TPing 控件最好用:
http://www.rtfm.be/fpiette/indexuk.htm

来自: sunstone, 时间: 2000-04-06 0:48:55, ID: 213477
g

来自: Liu JZX, 时间: 2000-04-06 20:10:13, ID: 214318
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.DFM}
Function MyPing(const Host:string):boolean;
var
CmdLinePChar:array[0..120] of char;
StartUpInfo:TStartUpInfo;
ProcessInfo:TProcessInformation;
HOutput:THandle;
StringList:TStringList;
TempFileName:String;
i:integer;
begin
Result:=false;
Screen.Cursor:=crHourGlass;
StringList:=TStringList.Create;
try
TempFileName:=ExtractFilePath(application.ExeName)+'tempfile.tmp';
HOutput:=FileCreate(TempFileName);
if HOutput<0 then
exit;
StrPCopy(CmdLinePChar,'Ping.exe'+Host);
FillChar(StartUpInfo,sizeof(StartUpInfo),#0);
with StartUpInfo do
begin
cb:=sizeof(StartUpInfo);
dwFlags:=STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
wShowWindow:=SW_HIDE;
hstdOutput:=HOutput;
end;
if CreateProcess(nil,CmdLinePChar,nil,nil,True,0,nil,nil,StartUpInfo,ProcessInfo) then
begin
WaitForSingleObject(Processinfo.hProcess,INFINITE);
FileClose(HOutput);
end
else
begin
FileClose(HOutput);
exit;
end;
StringList.LoadFromFile(TempFileName);
DeleteFile(TempFileName);
for i:=1 to StringList.Count-1 do
begin
if pos('Reply from',StringList)>=1 then
begin
Result:=true;
break;
end;
end;
finally
screen.Cursor:=crDefault;
form1.edit1.text:=stringlist;
StringList.Free;

end;

end;

procedure TForm1.Button1Click(Sender: TObject);
begin
MyPing(' jsj_ws8');
end;

end.


来自: coao, 时间: 2000-07-21 3:11:42, ID: 288630
问题太久,昨日刚解决

不好意思(现在发分)

来自: coao, 时间: 2000-07-21 3:17:31, ID: 288632
关注此题

来自: coao, 时间: 2000-07-21 3:18:43, ID: 288633
多人接受答案了。

得分大富翁: Big_Z-10,CaiFeng-10,Flintstone-10,Liu JZX-20,Pipi.-10,SuperMMX-10,wrench-10,www-10,程旭-10,
 
关于最小化的事件:
问题: 如何在按下一个Form右上角的最小化按钮后执行一些代码? ( 积分: 50 )
分类: Object Pascal

来自: phenix3344, 时间: 2003-05-11 15:07:00, ID: 1849344
???

来自: seagod007, 时间: 2003-05-11 15:47:00, ID: 1849433
用OnMinimize,帮助里有例子。
Application.OnMinimize

来自: LeeChange, 时间: 2003-05-11 15:55:00, ID: 1849458
在OnResize里用
if WindowState=wsMinimized then
就可以判断出最小化事件了.

来自: 小笨苯, 时间: 2003-05-11 16:02:00, ID: 1849483
这是完美的代码,不论是主窗体,还是子窗体,都适用。

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;

type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
procedure WMSysCommand(var Msg: TWMSysCommand); message WM_SYSCOMMAND;
end;

var
Form1: TForm1;

implementation

{$R *.DFM}

{ TForm1 }


{ TForm1 }

procedure TForm1.WMSysCommand(var Msg: TWMSysCommand);
begin
{ 如果想在按下最小化按钮后,只做你想做的事情,而不想让窗口最小化 }
if Msg.CmdType = SC_MINIMIZE then
ShowMessage('wo shi xiaobenben');
else
inherited;

{ 如果想在按下最小化按钮后,先做你想做的事情,再让窗口最小化 }
if Msg.CmdType = SC_MINIMIZE then
ShowMessage('wo shi xiaobenben');
inherited;

{ 如果想在按下最小化按钮后,先让窗口最小化,再做你想做的事情 }
inherited;
if Msg.CmdType = SC_MINIMIZE then
ShowMessage('wo shi xiaobenben');
end;

end.


来自: jacke_chen, 时间: 2003-05-11 16:15:00, ID: 1849511
procedure AppMessage(var Msg:TWMSYSCOMMAND);message WM_SYSCOMMAND;
procedure tform1.AppMessage(var Msg:TWMSYSCOMMAND);
begin
if msg.CmdType=sc_minimize then
showmessage('最小化')
else if Msg.CmdType = SC_Maximize then
showmessage('最大化');
inherited;
end;


来自: SuperYoyoNC, 时间: 2003-07-09 11:24:00, ID: 2014041
代码:
 if form1.WindowState=wsMinimized then form1.Close;

来自: Sea008, 时间: 2003-07-09 11:42:00, ID: 2014131
都说了,我还能说什么呢!

来自: fphuang, 时间: 2003-07-09 12:10:00, ID: 2014249
学习

来自: lgxyy, 时间: 2003-07-09 12:17:00, ID: 2014267
什么也不用说

来自: dfw1001, 时间: 2003-07-17 16:18:00, ID: 2037441
同上

来自: gxcooo, 时间: 2003-07-17 16:39:00, ID: 2037523
截取sc_minimize消息

来自: phenix3344, 时间: 2004-02-07 13:29:00, ID: 2441553
多人接受答案了。

问题讨论没有结束 ...
 
这样不行:
一:ping判断不了我的客户端程序状态,我需要的是在上面的代码基础上进行修改。
二:单击最小化按钮我已经实现,你给的和我的代码基本相同,我要的是单击任务栏使窗口最小化。
 
关于捕获异常的问题可用组件APPLICATIONEVENTS来解决.在其ONMESSAGE里有具体的信息,但这个出错被捕获是要在编译之后,在调试状态也是捕获不到的.我以前也是这样解决的.
 
后退
顶部