龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > 软件开发 > C/C++开发 >

用Indy组件开发Socket应用程序[组图]

时间:2009-12-22 15:42来源:未知 作者:admin 点击:
分享到:
笔者在前一段的工作中,需要开发一套简单的网络数据传输程序。由于平时常用Delphi做点开发,故此次也不例外。Delphi 7中带有两套TCP Socket组件:Indy Socket组件(IdTCPClient和IdTCPServer)和

  笔者在前一段的工作中,需要开发一套简单的网络数据传输程序。由于平时常用Delphi做点开发,故此次也不例外。Delphi 7中带有两套TCP Socket组件:Indy Socket组件(IdTCPClient和IdTCPServer)和Delphi原生的TCP Socket组件(ClientSocket和ServerSocket)。

更多内容请看Wlan组网----家庭专题专题,或 使用TIdAntiFreeze对抗“冻结”

  

  

  

  图1 Indy服务器工作原理

  

  使用组件TIdThreadMgrPool,Indy还支持线程池。 更多内容请看Wlan组网----家庭专题专题,或 线程与Indy客户程序

  

  Indy客户端组件并未使用线程。但是在一些高级的客户程序中,程序员可以在自定义的线程中使用Indy客户端组件,以使用户界面更加友好。

  

  简单的Indy应用示例

  

  

  图2 简单的TCP客户程序表单

  

  

  图3 简单的TCP服务器程序表单

  

  客户程序和服务器程序的表单上都放置有TListBox组件,用来显示通信记录。

  

  客户程序代码

  

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

  

  代码列表1

  

  

procedure TFormMain.BTnConnectClick(Sender: TObject);

  begin

  IdTCPClient.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方法断开连接。

  

  程序中还包含有通信信息记录和异常处理的代码。 更多内容请看Wlan组网----家庭专题专题,或

  

  服务器程序代码

  

  服务器程序片断如代码列表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. 按服务器程序的“停止”按钮停止服务器。

  

  程序运行的结果如图4和图5所示。

  

  

  

  图4 简单的TCP客户

  

  

  图5 简单的TCP服务器 更多内容请看Wlan组网----家庭专题专题,

  

  

精彩图集

赞助商链接