使用TServerSocket构件提供多线程服务

最近要写一个socket的多线程的服务,刚刚好从网上找到这篇文章,觉得有用,保存下来
      {
使用TServerSocket构件提供多线程服务
www.mynetlife.com  2002-12-29  网迷教程


使用TServerSocket构件提供多线程服务
对于一个socket来说,很容易提供一个侦听消息的多线程服务。Delphi自身也提供了这样的构件:TServerSocket。
不过这里边也需要一点小技巧。
为此,我们要做以下几件事:
-将TServerSocket加入main窗体中
-设置Servertype属性为stThreadBlocking
-生成一个新单元(如下)来包含服务线程
将下面的代码赋给OnGetThread事件响应函数
   }

procedure TfrmMain.fSocketGetThread(Sender: TObject;  ClientSocket: TServerClientWinSocket;  var SocketThread: TServerClientThread);

begin

// 在每次一个新连接建立的时候为它生成一个新的TServerThread对象。

  SocketThread := TServerThread.Create(FALSE, ClientSocket);

end;

       {下面是我自己生成的TServerThread对象代码.该对象从TServerClinetThread继承而来,包含从socket读写数据的代码。}
unit serverthread;

interface

uses

  windows, scktcomp, SysUtils, Classes, Forms;

type
  EServerThread = class(Exception);
// TServerThread服务线程类是TServerClientThread的派生类
  TServerThread = class(TServerClientThread)

  private
    fSocketStream: TWinSocketStream;

  public
    procedure ClientExecute; override;

// ClientExecute过程将覆盖TServerClientThread.ClientExecute过程
// 并包含实际执行的代码于线程开始时。
  end;

implementation

procedure TServerThread.ClientExecute;
begin
  inherited FreeOnTerminate := TRUE;
  try
    fSocketStream := TWinSocketStream.Create(ClientSocket, 100000);
   // 设置100000毫秒的充许超时.
    try
      while (not Terminated) and (ClientSocket.Connected) do
      try
      // 在此处加入你对输入、读、写的等待
      // 下面的示范你可以拿来照搬在此

      except on e: exception do begin
         // 一旦错误发生就关闭并退出
          ClientSocket.Close;
          Terminate;
        end;
      end;
    finally
      fSocketStream.Free;
    end;
  except on e: exception do  begin
     // 一旦错误发生就关闭并退出
      ClientSocket.Close;
      Terminate;
    end;
  end;
end;

      {一旦连接建立,线程需要等待数据到来.你可以使用下面的代码来等待数据:}
if (not Terminated) and (not fSocketStream.WaitForData(1000000)) then
begin
// 超时处理
end;

// 数据到达!
    {为了读取数据,我们需要建立一个数据缓冲区存取到达的数据,可以使用PByteArray或一个char型的数组.
在此例中我设置了一个名为fRequest的char型数组缓冲。此外我将其设为定长,其大小由REQUESTSIZE常量决定.}
var
  ac, readlen: integer;
begin
  FillChar(fRequest, REQUESTSIZE, 0);
  ac := 0;
  repeat
    readlen := fSocketStream.Read(fRequest[ac],1024);
    // 每次读取1024 bytes直到缓冲区满
    ac := ac + readlen;
  until (readlen = 0) or (ac = REQUESTSIZE);
end;
{
如果说readlen是 0 的话,说明我未收到任何数据.读函数的超时从TWinSocketStream.Create()执行后开始.如果说你不知道预期的数据量,你最好将超时设置得尽量小些.在大多数情况下 30 秒是上限.
当发送一个应答时,你应该很清楚客户端的行为.许多客户端仅仅等待一个应答包,一些则等待许多包.
在本例中,我只设置了一个客户端并只等待一个包,所以我们需要一次就将数据包发送出去。

fSocketStream.WriteBuffer( fRep, fReplySize );
fRep是应答缓冲区,fReplySize则是缓冲区大小.  }

posted on 2004-08-17 16:39  khan  阅读(3531)  评论(0编辑  收藏  举报

导航