__________________________________________路有尽,道无涯__________________________________________

【Profound__爱生活__诗意地栖息】

C/C++ || Python || Linux || 单片机 || 嵌入式 || 机器视觉

  博客园  :: 首页  :: 新随笔  ::  :: 订阅 订阅  :: 管理

http://blog.csdn.net/quicmous/article/details/4263115

最近使用了Delphi7提供的TcpCLient和TcpServer两个VCL控件,发现这两个控件使用非常简单,不像网上不少帖子说的那样难用、性能差。

TcpClient和TcpServer没有采用事件驱动的模式,而是采取了同步方法调用的策略(网上有帖子称之为阻塞模式),大大简化了编写Sockets通讯程序的过程。如果我们还停留在事件驱动的思维习惯上,就会发现很难使用这两个控件。

Delphi7提供了一个名为NetChat的演示程序,该程序展示了TcpClient和TcpServer的初步用法。

一、 数据的发送与接收

//数据发送代码:
procedure TForm1.btnSendClick(Sender: TObject);
var
  I: Integer;
begin
  TcpClient1.RemoteHost := edtRemoteHost.Text; //服务器IP
  TcpClient1.RemotePort := edtRemotePort.Text; //服务器端口号
  try
    if TcpClient1.Connect then
      for I := 0 to memSend.Lines.Count - 1 do
      TcpClient1.Sendln(memSend.Lines[I]);
  finally
    TcpClient1.Disconnect;
  end;
end;

//在OnAccept事件中接收数据(此处作了简化):
procedure TForm1.TcpServer1Accept(sender: TObject;
  ClientSocket: TCustomIpClient);
var
  s: string;
begin
  s := ClientSocket.Receiveln;
  while s <> '' do
  begin
    //此处对s做适当处理,代码略。
    s := ClientSocket.Receiveln;
  end;
end;

 

TcpServer在接收到数据后,只产生一个OnAccept事件。在OnAccept时间响应函数中,我们循环调用ClientSocket参数的Receiveln方法接受数据。让该方法返回空字符串时,意味着连接已经断开

需要注意的是:
1.Receiveln方法在客户端没有传送数据时一直处于等待状态。
2.演示程序用s <> ''判断连接是否断开,下面我们可以看到其它判断方法。

二、 TcpServer的OnAccept事件中的参数ClientSocket

OnAccept事件响应函数带一个名为ClientSocket的参数,该参数是一个TCustomIpClient类型的对象。利用该参数可以方便我们访问客户端信息(客户端IP、端口等),并管理连接。

前面我们看到可以利用Receiveln返回空值的条件判断连接是否结束。如果希望实现超时断开连接功能的话,可以采用ClientSocket对象的WaitForData方法,等待数据。该方法允许指定等待时间,方法声明如下:

function WaitForData(TimeOut: Integer = 0): boolean;

可以调用ClientSocket的Disconnect方法在退出前断开连接

三、 关于OnAccept多线程的问题

在同时收到多个客户端信息时,OnAccept应该在内存存在多个线程实例。因此,在OnAccept的代码,必须符合多线程设计原则。

Delphi的VCL库和其它一些组件是面向单线程设计的。这表明对VCL控件等组件的调用,必须通过TThread类的Synchronize方法调用。在NetChat这个演示程序中,提供了相应的代码供参考。更多资料请参考Delphi多线程编程的相关资料。

四、从服务器返回数据

如果需要从服务器返回数据的话,只需要在OnAccept中调用ClientSocket.Sendln方法即可。

客户端需要做的就是在执行完TcpClient1.Sendln后,直接调用 TcpClient1.Receiveln即可。该方法会等待服务器传回的信息。当然如果希望超时断开的话,也可以调用WaitForData方法,判断在给定时间内是否有数据返回。

四、 常见问题

问题:为什么TcpClient的OnReceive事件不响应服务器传回的数据?

原因很简单,OnReceive事件是由TcpClient的Receiveln等函数激发的,用于在Receiveln等函数接受到数据之前过滤数据用。

因此,如果你不调用TcpClient的Receiveln等函数,OnReceive事件就永远不会被激发。

posted on 2016-08-02 16:57  HiRong  阅读(4538)  评论(0编辑  收藏  举报
__________________________________________路有尽,道无涯__________________________________________