• delphi TServerSocket阻塞线程单元 实例


    TServerSocket阻塞线程单元,希望对你有所帮助。需要注意的是:
    1、如果你使用TServerSocket的stNonBlocking模式,重写TServerClientThread线程时要重载
    TServerClientThread的ClientExecute过程,写你自己的处理过程;
    2、如果在线程内部调用外部的过程,建议使用同步化方法;
    3、线程访问线程内部变量的速度远远高于线程访问线程内部变量的速度
    如果有问题的话,可以和我联系 Email: rurality@21cn.com

    //**********************************************************************************
    //说明: TServerSocket阻塞线程
    //作者: licwing          时间: 2001-4-21
    //Email: rurality@21cn.com
    //**********************************************************************************
    unit BlockThread;

    interface

    uses SysUtils, Windows, Messages, Classes, ScktComp,ProxyCnt;

    type
      TBlockThread = Class(TServerClientThread)
      private
        FWebClient: TClientSocket; //对web进行数据请求
        FWebClientRead: Boolean; //是否可以对web进行数据请求
        FRequestInfo: string;
        FReceiveInfo: TReceiveInfo; //接收的数据流信息
        FRecBytesFromWebSend: Integer; //已接收到的Web数据字节数
        FWebSendBytes: Integer; //Web服务器需要发送的总字节数
       
        Receive_buf: array[0..8191] of char; //接收缓冲区
        Request_buf: array[0..8191] of char; //发送缓冲区,用来保存客户端的请求数据
        Request_buf_bytes: integer; //发送缓冲区已经接收的字节数
        FReceiveInfoSaved : boolean ; //接收的数据头信息保存标志

        procedure  InitThread;
        function  SetWebClientInfo(FRequestURLInfo: String): boolean;
      protected
        procedure ClientExecute; override;
        procedure DoTerminate; override;
      public
        constructor Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket);
        destructor Destroy; override;
      end;

    implementation

    //TProxyClientThread
    constructor TBlockThread.Create(CreateSuspended: Boolean; ASocket: TServerClientWinSocket);
    begin
      FWebClient := TClientSocket.Create(nil);
      FWebClient.ClientType := ctBlocking;

      inherited Create(CreateSuspended,ASocket);
      InitThread;
    end;

    destructor TBlockThread.Destroy;
    begin
      FWebClient.Free;
      inherited Destroy;
    end;

    procedure TBlockThread.InitThread;
    begin
      FRecBytesFromWebSend := 0;
      FWebSendBytes := 0;
      Request_buf_bytes := 0;
      FReceiveInfoSaved := false;
      FWebClientRead := false;
    end;

    function TBlockThread.SetWebClientInfo(FRequestURLInfo: String): boolean;
    var
      URL_info: TURLHostInfo;
      FWebFilter: boolean;
    begin
      URL_info := GetURLHostPort(FRequestURLInfo);
      Result := ( URL_info.HostName <> '' ) and ( URL_info.HostPort > 0 );
      FWebClient.Port := URL_info.HostPort;
      FWebClient.Host := URL_info.HostName;
    end;

    procedure TBlockThread.DoTerminate;
    begin
      FRecBytesFromWebSend := 0;
      FWebSendBytes := 0;
      FRequestInfo := '';
      FReceiveInfoSaved := false;
      FWebClientRead := false;
      inherited DoTerminate;
    end;

    procedure TBlockThread.ClientExecute;
    var
      ReceiveStream,
      RequestStream: TWinSocketStream;
      Rec_Bytes: integer;
    begin
     //获取和处理命令直到连接或线程结束
      while (not Terminated) and (ClientSocket.Connected) do
        try //try 1
          //创建TWinSocketStream对被代理端进行读写操作
          RequestStream := TWinSocketStream.Create(ClientSocket, 60000);
          try  //try 2
            //获取被代理端请求
            Request_buf_bytes := RequestStream.Read(Request_buf,8192);
            //如果有请求,设置Web端信息
            if Request_buf_bytes > 0 then FWebClientRead := SetWebClientInfo(Request_buf);
            //Web端通信准备完成,并且访问站点没有被过滤  IfID=1
            if FWebClientRead  then 
              begin //IFID=1 begin Then method
              try  //try 3
                //Web端开始通信
                ReceiveStream := TWinSocketStream.Create(FWebClient.Socket, 60000);
                FWebClient.Active := True;
                  try //try 4
                    //向Web端发送请求
                    ReceiveStream.Write(Request_buf,Request_buf_bytes);
                    while (not Terminated) and (FWebClient.Socket.Connected) do
                    begin
                      //接收Web端返回的数据
                      Rec_bytes := ReceiveStream.Read(Receive_buf,8192);

                      Inc(FRecBytesFromWebSend,Rec_bytes);
                      //保存Web端返回数据的信息
                      if not FReceiveInfoSaved then
                        begin
                          FReceiveInfo := AnalyzeReceiveData(Receive_buf);
                          FReceiveInfoSaved := FReceiveInfo.ContentInfo.RequestFound;
                          FWebSendBytes := FReceiveInfo.ContentInfo.ContentSize +
                                       FReceiveInfo.RemoteFileInfo.RemoteFileSize;
                        end;
                      //如果被代理端还连接,传送Web端返回的数据
                      if ClientSocket.Connected then

                       RequestStream.Write(Receive_buf,Rec_Bytes);
                      if ( FRecBytesFromWebSend >= FWebSendBytes ) or ( Rec_bytes = 0 )
                       or not ClientSocket.Connected then FWebClient.Close;
                    end;
                  finally  //try 4
                    ReceiveStream.Free;
                  end;
              finally  //try 3
                ClientSocket.Close;
              end;
            end  //IFID=1 end Then method
            else //IFID=1 begin else method
              begin//发送拒绝请求信息到客户端
               // RequestStream.Write(AccessLimit,sizeof(AccessLimit));
              end;
          finally  //try 2
            RequestStream.Free;
            Terminate;
          end;
        except  //try 1
          // HandleException;
        end;
    end;

    end.


    //**********************************************************************************
    // TServerSocket阻塞线程调用方法
    //**********************************************************************************
    procedure TfrmMain.ServerSocketGetThread(Sender: TObject;
      ClientSocket: TServerClientWinSocket;
      var SocketThread: TServerClientThread);
    begin
      SocketThread := TBlockThread.Create(false,ClientSocket);
    end;

  • 相关阅读:
    秒杀场景:如何通过 Redis 减库存?
    eclipse启动报failed to find a Main Class in C:\users\2008nmj\eclipse\java201812\eclipse....jar
    pgr_createTopology创建网络失败。。
    Cesium之Sandbox
    java JDK版本修改不生效的解决方法
    云上360行丨深耕快消品行业数字化转型,纷享销客与华为云合力同行
    华为云Stack首席架构师:打造“称手”的数字化工具,答好政企IT数字化转型这道必选题
    认识一下什么是JSP
    想发自己的NFT,你要先搞清楚这6个问题
    教你搭建一个Telegraf+Influxdb+Grafana 监控系统
  • 原文地址:https://www.cnblogs.com/zhangzhifeng/p/5867188.html
Copyright © 2020-2023  润新知