TServerSocket阻塞模式下RequestResponse编程框架

摘要:
在Delphi6中TServerSocket的TThreadBlocking模式下,OnRead/OnWrite事件在主线程中执行。虽然它是多线程的,但实际效率并不高。因此,如果我们需要使用TServerSocket来开发真正的多线程服务器,我们需要编写TServerClientThread的子类。在这个子类中,我们可以自己处理数据的接收和发送,重写的重点是ClientExecute方法。以下是代码说明

Delphi6中的TServerSocket在线程阻塞模式(TThreadBlocking)下,OnRead/OnWrite事件的是在主线程中执行的,虽为多线程,实际效率不高。
故我们若需要利用TServerSocket来开发真正多线程的服务器,则需要写TServerClientThread的子类,在这个子类中,自行处理数据的接收与发送,而重写的的重点在ClientExecute方法。下面为代码描述了这种编程思路。


type
  TServerForm=class(TForm)
  ...
  private
    procedure  GetThread(Sender: TObject; ClientSocket: TServerClientWinSocket; var SocketThread: TServerClientThread);
  end;

type
  TMyServerClientThread=class(TServerClientThread)
  private
    function WaitForData(TimeOut:Integer):Boolean;
  protected
    procedure ClientExecute;override;
  end;

implementation

{ TMyServerClientThread }

function TMyServerClientThread.WaitForData(TimeOut: Integer): Boolean;
var
  FDSet:TFDSet;
  TimeVal:TTimeVal;
begin
  FD_ZERO(FDSet);
  FD_SET(ClientSocket.SocketHandle,FDSet);
  TimeVal.tv_sec:=TimeOut div 1000;
  TimeVal.tv_usec:=TimeOut mod 1000;
  Result:=select(0,@FDSet,nil,nil,@TimeVal)>0
end;

procedure TMyServerClientThread.ClientExecute;
var
  InputBuffer:TSockBuffer;
  iLen,iPos:Integer;
  sCmd:string;
  tmpBuf:string;
begin
  InputBuffer:=TSockBuffer.Create;
  try
    while not Terminated and ClientSocket.Connected do
    begin
      if WaitForData(500) and not Terminated then
      begin
        iLen:=ClientSocket.ReceiveLength;
        if iLen=0 then
        begin
          Break
        end else
        begin
          SetLength(tmpBuf,iLen);
          ClientSocket.ReceiveBuf(tmpBuf[1],iLen);
          InputBuffer.WriteBuffer(tmpBuf[1],iLen);
          iPos:=InputBuffer.Pos(EOL);
          if iPos>0 then
          begin
            sCmd:=InputBuffer.Extract(iPos+1);
            Delete(sCmd,Length(sCmd)-1,2);
            if CmdList.IndexOf(sCmd)>-1 then
              ClientSocket.SendText('+OK');
            if SameText(sCmd,'EXIT') then
              Break;
          end;
        end;
      end;
    end;
  finally
    InputBuffer.Free;
  end;
end;


{ TServerForm }

procedure TServerForm.FormCreate(Sender: TObject);
begin
  with TServerSocket.Create(Self) do
  begin
    Port:=4001;
    ServerType:=stThreadBlocking;
    OnGetThread:=GetThread; //这一步是关键,OnGetThread事件产生时,创建自己的线程。
    Active:=True;
  end;
end;

procedure TServerForm.GetThread(Sender: TObject;
  ClientSocket: TServerClientWinSocket;
  var SocketThread: TServerClientThread);
begin
  SocketThread:=TMyServerClientThread.Create(False,ClientSocket);
end;

免责声明:文章转载自《TServerSocket阻塞模式下RequestResponse编程框架》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇SQL SERVER 2005 数据挖掘与商业智能完全解决方案学习笔记(四)全网最详细的Git学习系列之介绍各个Git图形客户端(Windows、Linux、Mac系统皆适用ing)(图文详解)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

ssh登录时在参数中加入密码的解决方案

在使用ssh登录远程服务器的时候,在执行完sshuser@ip后,要输入登录密码,有时候登录密码记不住,这样以来Ian带来的很多的麻烦,有没有一种在ssh的参数中直接加入密码的方法呢?查看ssh的帮助我们发现ssh命令并不能在参数中制定密码。usage:ssh[-1246AaCfGgKkMNnqsTtVvXxYy][-bbind_address][-ccip...

用python调用caffe时出错:AttributeError: 'module' object has no attribute 'bool_'

下面给出了一个解决方案,即重命名冲突的io文件:numpyと PyCaffe公司が io。年が 竞争す る よ で す$ pythonclassify。py--raw_scale255~/caffe/101_ObjectCategories/airaires/image_0001.jpg../result.npyTraceback:文件“classif.py...

Revit导入lumion渲染

利用Revit导出DAE文件格式插件,可以将Revit模型导入到lumion中进行图片渲染和漫游动画的制作。lumion强大的漫游功能,丰富的附加组件,绚丽的视频特效。lumion没有建模功能,但是Revit建模的没有统一的标准,导致一些不该同样的材质的地方,无法更改;如果有统一的标准,那么Revit结合lumion能做出任何想要的效果。Revit13版本能...

beego

Charset=utf8“)56//参数4(可选)设置最大空闲连接7//参数5modelorm.RegisterModelRegisterModelWithPrefix。使用表名前缀orm.RegisterModelWithPrefixbeego自动创建表。1//参数1使用默认数据库ORM接口使用1//查询操作2funread(){3o:=ORM.NewOr...

webstorm关闭烦人的eslint语法检查

使用eslint语法检查后,我们发现JS代码中到处都是红线。通过右键菜单中的fixeslint problems选项,我们可以发现页面代码格式完全被eslint包装。只需关闭exlint语法检查。看不见,想不起来。反向关闭不会影响代码开发,但相反,它会影响代码开发。关闭eslint位置:文件--˃设置--˃语言和框架--˃CodeQualityTools--...

Winform知识点

BringToFront()将控件移动到Z顺序的前面。...