• TServerSocket阻塞模式下RequestResponse编程框架


    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;

  • 相关阅读:
    微信小程序开发前期准备
    怎样在vs2013和vs2015中实现自动编译sass
    在MVC中使用Bundle打包压缩js和css
    Html5 突破微信限制实现大文件分割上传
    Automapper 实现自动映射
    Polly一种.NET弹性和瞬态故障处理库(重试策略、断路器、超时、隔板隔离、缓存、回退、策略包装)
    关于transactionscope 事务的脏数据
    IIS设置session时长
    已禁用对分布式事务管理器(MSDTC)的网络访问的解决方法之一
    DAL.SQLHelper 的类型初始值设定项引发异常的处理
  • 原文地址:https://www.cnblogs.com/hnxxcxg/p/2940629.html
Copyright © 2020-2023  润新知