分享

如何使用TTcpServer控件

 ZLM_图书馆 2014-03-04

如何使用TTcpServer控件

 

一直想学习一下网络编程,苦于无法找到相关的资料,以前也写过一些网络程序,但那些都是用Indy的控件,使用起来相对较为简单,无法接触到底层的东西。最近安装了VISTA操作系统后,发现该系统彻底的不支持Delphi  7了。在网上下载了Delphi 2006 Lite版,少了很多控件,其中就包括了以前用的Indy控件,但幸运的是可以使用TTcpServerTTcpClient控件。但这个控件基本上不会使用,在网上查找相关的资料也相当的困难,论坛中基本上是问这个控件怎么使用的,回答的也多是一些错的。另外该死的VISTA系统也不支以前的老的帮助,幸运的是该控件带有源代码,经过几天的研究。终于了解了该控件的使用方法。下面介绍一下该控件的使用方法以及相关的注意事项。

这个控件的属性不多,其他的属性没什么好介绍的,都可以顾名思义的设就形了,需要一提的是BlockMode,本文着重介绍当BlockModebmBlocking的使用方法。这种阻塞模式为线程阻塞,其实也就是阻塞模式,当调用Open的方法后,系统自动会开启一个线程来监控是否有客户端连接。如果有客户端的连接过来后,系统会自动为每个客户端提供一个线程。这个线程会有一个默认线程类来实现的,但该类基本上没有什么功能,如果想使用TTcpServer这个类的话,那么这个类的代码是必须要重写的。

客户端线程类的写法:

  TServerThread=class(TClientSocketThread)
  private
    s:string;
  protected
    procedure SyncProc;override;
  end;

TServerThread }

procedure TServerThread.SyncProc;
begin
  form1.Memo1.Lines.Add(formatdatetime(
'mm-dd hh:mm:ss :',now)+s);
end;

该控件提供的事件也不是很多,需要注意使用的有两个,一个是OnGetThread,另外一个是OnAccept。只要在这两个里面进行编码就基本上就可以使用这个类了。OnGetThread里面需要写的代码是用自己的线程类来替换掉默认的主线程类。OnAccept里面需要写的代码是主线程类中需要处理的任务,如读取客户端的消息,向客户端回应等。需要注意的是OnAccept的代码是在线程中运行,需要写成死循环,除非到该客户端中止为止,并且还需要不停的去检查该线程是否中止。另外如果访问主线程中的资源,需要进行同步处理。以下是这个两个方法的代码示例:

1OnGetThread中取代线程的代码

procedure TForm1.TcpServer1GetThread(Sender: TObject;
  var ClientSocketThread: TClientSocketThread);
begin
  ClientSocketThread:=TServerThread.Create(tcpserver1.ServerSocketThread);
end;

2OnAccept中的代码

procedure TForm1.TcpServer1Accept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var T:TServerThread;
begin
  T:=TServerThread(ClientSocket.GetThreadObject);
  T.s :=clientsocket.RemoteHost +
'已连接';
  t.SyncProc 
  while not T.Terminated and clientsocket.Connected do
  begin
    if ClientSocket.WaitForData(
0then
    begin
      t.s:=ClientSocket.Receiveln();
      ClientSocket.Sendln(
'Re:'+t.s);
      if t.s=
'QUIT' then ClientSocket.Disconnect
      else T.SyncProc;
    end;
  end;
  t.s :=clientsocket.RemoteHost +
'已断开';

  t.SyncProc 
end;

以上的代码写好后,该控件就可以正常工作了。这个程序的功能比较简单,客户发过来消息后,自动回应客户一条信息。如果收到客户退出的消息后,就会自动退出线程,并中止与客户端的连接。

总而言之,这个控件封装的还是不错的,只需要简单的和行代码就可以实现复杂的服务器程序。下面是这个程序完整的例子:

unit Unit1;
{
  
项目TTcpServer 示例程序
  
作者黄涛
  
创建2008-4-25
}

interface

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

type
  TForm1 class(TForm)
    btStart: TButton;        
//开始终止按钮
    Server: TTcpServer;      
//服务器控件
    mmLog: TMemo;            
//日志控件
    procedure ServerGetThread(Sender: TObject;    
//获取线程的事件
      var ClientSocketThread: TClientSocketThread);
    
//客户端连接事件
    procedure ServerAccept(Sender: TObject; ClientSocket: TCustomIpClient);
    procedure btStartClick(Sender: TObject); 
//点击启动中止事件
    procedure AddLog(msg:String);
//添加日志
  private
    
Private declarations }
  public
    
Public declarations }
  end;

  TServerThread=class(TClientSocketThread)   
//客户端线程
  private
    s:string;
  protected
    procedure SyncProc;override;    
//同步的方法
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.AddLog(msg: String);     
//添加日志
begin
  mmLog.Lines.Add(formatdatetime(
'mm-dd hh:mm:ss :',now)+msg);
end;

procedure TForm1.btStartClick(Sender: TObject);
begin
  if server.Active then Server.close
  else Server.Open  
  if Server.Active then
  begin
    btStart.Caption :=
'停止' 
    AddLog(
'服务器已启动'
  end
  else
  begin
    btStart.Caption :=
'启动';
    AddLog(
'服务器已停止');
  end;
end;

procedure TForm1.ServerAccept(Sender: TObject;
  ClientSocket: TCustomIpClient);
var T:TServerThread;
begin
  T:=TServerThread(ClientSocket.GetThreadObject); 
//获取该线程的对象句柄
  T.s :=clientsocket.RemoteHost +
'已连接';
  T.ExecuteSyncProc;     
//添加已连接的日志
  while not T.Terminated and clientsocket.Connected do
  begin   
//该线程未中止和客户端未中止连接时执行
    if ClientSocket.WaitForData(
0then
    begin  
//如果客户端发送数据
      t.s:=ClientSocket.Receiveln();   
//接收数据
      ClientSocket.Sendln(
'Re:'+t.s);  //回复客户端
      if t.s=
'QUIT' then ClientSocket.Disconnect //如果是退出指令,则断开连接
      else T.SyncProc; 
//否则添加日志
    end;
  end;
  t.s :=clientsocket.RemoteHost +
'已断开'  //添加断开客户端的日志
  T.ExecuteSyncProc;
end;

procedure TForm1.ServerGetThread(Sender: TObject;
  var ClientSocketThread: TClientSocketThread);
begin     
//用自己的线程取代标准的端线程
  ClientSocketThread:=TServerThread.Create(Server.ServerSocketThread);
end;

TServerThread }

procedure TServerThread.SyncProc;
begin
  Form1.AddLog(s);   
//添加日志
end;

end.

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多