INDY组件中IdTcpClient怎么样监控指定的端口,一有数据进来,先触发什么事件?

afeng124 2005-10-15 09:13:38
INDY组件中IdTcpClient怎么样监控指定的端口,一有数据进来,先触发什么事件?

onwork
onworkbegin
onworkend
还是onstatus
onstatus,有几种status,不知怎么用,需要做一个tcp客户端按即定的通信方式通信。
比如收到字符"PA"开头的字符串时,我要记录和拆分收到的字符串。我现在用了一个time控件在
ontime事件中写接收的代码。
procedure Tfrm_wwwifc_main.Timer1Timer(Sender: TObject);
begin
if bitbtn8.Tag=1 then
if not busy then
begin
revbuf:=IdTCPClient1.ReadString(70);
if trim(revbuf)<>'' then
splil_billinfo(trim(revbuf));
end;
end;
每一秒钟运行一次,我连接后触发time的ontime后,程序就像死机了一样。

请有经验的同志,帮助看看。谢谢。
...全文
652 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
afeng124 2005-10-17
  • 打赏
  • 举报
回复
谢谢kv2002(笑三少),问题已解决,忘记上来结帐,就是看了indy10下的tcpchardemo后觖决的。
afeng124 2005-10-15
  • 打赏
  • 举报
回复
先谢谢 lovendII(戒情人) 我动手写东西之前就是参照这个例子。现在我的程序收发数据正常,
每次在发送到服务器端后readln都有返回数据。但是服务器端会不定时的发数据过来。我不知道
怎么监听服务器端是否发了数据过来。idTCPclient,只有有限的以下事件:
onconnecting;onstatus;onwork;workbegin;workend;
没有onreving这样的事件,我怎么监听到服务有数据过来,再去缓冲区去读呀。我现在就是每隔一秒
读一次缓冲区,这样不行,程序会没有反应。

请有经验的同志,说说经验,分不够再加。

谢谢。
lovendII 2005-10-15
  • 打赏
  • 举报
回复
http://www.ccw.com.cn/cio/research/program/htm2003/20031126_14CLP_2.asp

在Delphi 7 中用Indy开发Socket应用程序

客户程序代码

客户程序片断如代码列表1所示。

代码列表1

procedure TFormMain.BtnConnectClick(Sender: TObject);

begin

Id
TCPClient.Host := EdtHost.Text;

IdTCPClient.Port := StrToInt(EdtPort.Text);

LbLog.Items.Add('正在连接 ' + EdtHost.Text + '...');

with IdTCPClient do

begin

try

Connect(5000);

try

LbLog.Items.Add(ReadLn());

BtnConnect.Enabled := False;

BtnSend.Enabled := True;

BtnDisconnect.Enabled := True;

except

LbLog.Items.Add('远程主机无响应!');

IdTCPClient.Disconnect();

end;//end try

except

LbLog.Items.Add('无法建立到' + EdtHost.Text + '的连接!');

end;//end try

end;//end with

end;


procedure TFormMain.BtnSendClick(Sender: TObject);

begin

LbLog.Items.Add('DATA ' + EdtData.Text);

with IdTCPClient do

begin

try

WriteLn('DATA ' + EdtData.Text);

LbLog.Items.Add(ReadLn())

except

LbLog.Items.Add('发送数据失败!');

IdTCPClient.Disconnect();

LbLog.Items.Add('同主机 ' + EdtHost.Text + ' 的连接已断开!');

BtnConnect.Enabled := True;

BtnSend.Enabled := False;

BtnDisconnect.Enabled := False;

end;//end try

end;//end with

end;


procedure TFormMain.BtnDisconnectClick(Sender: TObject);

var

Received: string;

begin

LbLog.Items.Add('QUIT');

try

IdTCPClient.WriteLn('QUIT');

finally

IdTCPClient.Disconnect();

LbLog.Items.Add('同主机 ' + EdtHost.Text + ' 的连接已断开!');

BtnConnect.Enabled := True;

BtnSend.Enabled := False;

BtnDisconnect.Enabled := False;

end;//end try

end;


在“连接”按钮事件响应过程中,首先根据用户输入设置IdTCPClient的主机和端口,并调用IdTCPClient的Connect方法向服务器发出连接请求。然后调用ReadLn方法读取服务器应答数据。

在“发送”按钮事件响应过程中,调用WriteLn方法写DATA命令,向服务器发送数据。

在“断开”按钮事件响应过程中,向服务器发送QUIT命令,并调用Disconnect方法断开连接。

程序中还包含有通信信息记录和异常处理的代码。

服务器程序代码

服务器程序片断如代码列表2所示。

代码列表2

procedure TFormMain.BtnStartClick(Sender: TObject);

begin

IdTCPServer.DefaultPort := StrToInt(EdtPort.Text);

IdTCPServer.Active := True;

BtnStart.Enabled := False;

BtnStop.Enabled := True;

LbLog.Items.Add('服务器已成功启动!');

end;


procedure TFormMain.BtnStopClick(Sender: TObject);

begin

IdTCPServer.Active := False;

BtnStart.Enabled := True;

BtnStop.Enabled := False;

LbLog.Items.Add('服务器已成功停止!');

end;


procedure TFormMain.IdTCPServerConnect(AThread: TIdPeerThread);

begin

LbLog.Items.Add('来自主机 '

+ AThread.Connection.Socket.Binding.PeerIP

+ ' 的连接请求已被接纳!');

AThread.Connection.WriteLn('100: 欢迎连接到简单TCP服务器!');

end;


procedure TFormMain.IdTCPServerExecute(AThread: TIdPeerThread);

var

sCommand: string;

begin

with AThread.Connection do

begin

sCommand := ReadLn();

FLogEntry := sCommand + ' 来自于主机 '

+ AThread.Connection.Socket.Binding.PeerIP;

AThread.Synchronize(AddLogEntry);

if AnsiStartsText('DATA ', sCommand) then

begin

FReceived := RightStr(sCommand, Length(sCommand)-5);

WriteLn('200: 数据接收成功!');

AThread.Synchronize(DisplayData);

end

else if SameText(sCommand, 'QUIT') then begin

FLogEntry := '断开同主机 '

+ AThread.Connection.Socket.Binding.PeerIP

+ ' 的连接!';

AThread.Synchronize(AddLogEntry);

Disconnect;

end

else begin

WriteLn('500: 无法识别的命令!');

FLogEntry := '无法识别命令:' + sCommand;

AThread.Synchronize(AddLogEntry);

end;//endif

end;

end;


procedure TFormMain.DisplayData();

begin

EdtData.Text := FReceived;

end;


procedure TFormMain.AddLogEntry();

begin

LbLog.Items.Add(FLogEntry);

end;


“启动”按钮设置IdTCPServer 的Active属性为True来启动服务器,“停止”按钮设置Active属性为False来关闭服务器。

IdTCPServerConnect方法作为IdTCPServer 的OnCorrect事件响应过程,向客户端发送欢迎信息。OnCorrect事件在一个客户连接请求被接受时发生,为该连接创建的线程AThread被作为参数传递给IdTCPServerConnect方法。

IdTCPServerExecute方法是IdTCPServer 的OnExecute事件响应过程。OnExecute事件在TIdPeerThread对象试图执行其Run方法时发生。OnExecute事件与通常的事件有所不同,其响应过程是在某个线程上下文中执行的,参数AThread就是调用它的线程。这一点很重要,它意味着可能有多个OnExecute事件响应过程被同时执行。在连接被断开或中断前,OnExecute事件响应过程会被反复执行。

在IdTCPServerExecute方法中,首先读入一条指令,然后对指令进行判别。如果是DATA指令,就解出数据并显示它。如果收到的是QUIT指令,则断开连接。需要特别指出的是,由于IdTCPServerExecute方法在某一线程上下文中执行,因此显示数据和添加事件记录都是将相应的方法传递给Synchronize调用来完成的。

运行程序

运行客户端和服务器程序,按如下流程进行操作:

1.按服务器程序的“启动”按钮启动服务器;

2.按客户程序的“连接”按钮,建立同服务器的连接;

3.在客户程序的待发送数据编辑框中输入“Hello, Indy!”,并按“发送”按钮发送数据;

4.按客户程序的“断开”按钮,断开同服务器的连接;

5.按服务器程序的“停止”按钮停止服务器。

afeng124 2005-10-15
  • 打赏
  • 举报
回复
up
afeng124 2005-10-15
  • 打赏
  • 举报
回复
up
kv2002 2005-10-15
  • 打赏
  • 举报
回复
你可以参考indy9 memo下得例子IdTCPDemo呀,客户端用线程接收啊.
{------------------------------通讯客户端消息程-------------------------}
type
TClientMessageThread = class(TThread)
private
MsgCommand: string; //消息命令
procedure HandleMessage;
protected
procedure Execute; override;
end;
{---------------------------------------------------------------------}

if not IdClient.Connected then
begin
// 如何获得主机IP和Port
IdClient.Host := Dm_send.ServerIP;
IdClient.Port := Dm_send.ServerPort;
try
IdClient.Connect(10000);
ClientThread := TClientMessageThread.Create(True);
ClientThread.FreeOnTerminate := True;
ClientThread.Resume;
except
on E: Exception do
begin
MessageDlg('连接服务器错误:' + #13 + E.Message, mtError, [mbOk], 0);
Application.Terminate;
end;
end;
end

procedure TClientMessageThread.Execute;
begin
try
while not Terminated do
begin
if not Fm_Main_Client.IdClient.Connected then
Terminate
else
try
MsgCommand := Fm_Main_Client.IdClient.ReadLn();
Synchronize(HandleMessage);
except
end;
end;
except
end;

end;
procedure TClientMessageThread.HandleMessage;
var
MsgID: Integer;
begin
MsgID := StrToInt(Trim(Copy(MsgCommand, 1, 2)));
case MsgID of
0: ;
1: ;

end;
end;
afeng124 2005-10-15
  • 打赏
  • 举报
回复
up

1,593

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 网络通信/分布式开发
社区管理员
  • 网络通信/分布式开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧