Windows新异步网络编程模型4 RIO-RAW封包拦截

unit RIO_RAW_GetPacket;
//chatGPT写的
uses
  Winapi.WinSock, Winapi.Windows;

const
  IPPROTO_RIO = 0x6F;
  TCP_PROTOCOL = 6;
  RIO_RECV = 0;
  RIO_SEND = 1;
  RIO_BUF_SIZE = 1024;

type
  PRIO_BUFFER = ^RIO_BUFFER;
  RIO_BUFFER = packed record
    Length: ULONG;
    BufferId: ULONG;
  end;

var
  WSAData: TWSAData;
  Socket: TSocket;
  SockAddr: TSockAddr;
  Buffer: array[0..RIO_BUF_SIZE - 1] of Byte;

function LoadRioExtensionFunctions(Socket: TSocket): Boolean;
var
  Rio: RIO_EXTENSION_FUNCTION_TABLE;
  RioBuffer: array[0..MAX_PATH] of Byte;
  BytesReturned: DWORD;
begin
  // 将 WSAIoctl 函数用于 SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER 命令以获取 RIO 扩展功能表
  Result := (WSAIoctl(Socket, SIO_GET_MULTIPLE_EXTENSION_FUNCTION_POINTER,
    @RioBuffer, SizeOf(RioBuffer), @Rio, SizeOf(Rio), @BytesReturned, nil, nil) = 0);
end;

function GetProcessId(const SockAddr: TSockAddr): DWORD;//TSocket转TSockAddr用getsockname
var
  dwProcessId: DWORD;
begin
  // 从地址中获取套接字所属进程的 ID
  GetOwnerModule(SockAddr, dwProcessId);//function GetOwnerModule(SockAddr: PSockAddr; var dwProcessId: DWORD): HMODULE; stdcall; external 'iphlpapi.dll';
  Result := dwProcessId;
end;

function RioGetCompletionStatus(const CQ: PRIO_CQ; const Entries: ULONG;
  const NotificationCount: ULONG; const Timeout: ULONG;
  out Results: PRIORESULT): ULONG;
begin
  // 获取 RIO 完成队列中的完成结果
  Result := RIOGetCompletionStatus(CQ, Results, Entries, NotificationCount, Timeout);
end;

procedure RioPostRecv(const Rio: RIO_EXTENSION_FUNCTION_TABLE; const RQ: PRIO_RQ;
  const Buffer: PRIO_BUFFER; const DataBufferCount: ULONG; const RequestContext: Pointer);
begin
  // 向 RIO 请求队列中提交接收请求
  Rio.RIOReceiveEx(RQ, @Buffer, DataBufferCount, nil, nil, nil, 0, 0, RequestContext);
end;

procedure RioPostSend(const Rio: RIO_EXTENSION_FUNCTION_TABLE; const RQ: PRIO_RQ;
  const Buffer: PRIO_BUFFER; const DataBufferCount: ULONG; const RequestContext: Pointer);
begin
  // 向 RIO 请求队列中提交发送请求
  Rio.RIOSendEx(RQ, @Buffer, DataBufferCount, nil, nil, nil, 0, 0, RequestContext);
end;

procedure ProcessPacket(const Packet: PByte; const PacketLength: DWORD);
begin
  // 处理收到的网络封包
  // ...
end;

procedure Main;
var
  Rio: RIO_EXTENSION_FUNCTION_TABLE;
  CQ: RIO_CQ;
  RQ: RIO_RQ;
  Buffer: array[0..RIO_BUF_SIZE - 1] of RIO_BUFFER;
  RequestContext: array[0..RIO_BUF_SIZE - 1] of Pointer;
  ProcessId: DWORD;
  NumEntries: ULONG;
  Results: array[0..RIO_BUF_SIZE - 1] of RIORESULT;
  PacketLength: DWORD;
  CompletionResult: ULONG;
  i: Integer;
begin
    // 初始化 Winsock
    if WSAStartup(MAKEWORD(2, 2), WSAData) <> 0 then
    begin
        Exit;
    end;

    // 创建原始套接字并启用 RIO 扩展
    Socket := WSASocket(AF_INET, SOCK_RAW, IPPROTO_RIO, nil, 0, WSA_FLAG_REGISTERED_IO);
    if Socket = INVALID_SOCKET then
    begin
        WSACleanup;
        Exit;
    end;

    // 绑定套接字并设置过滤器以便只接收指定进程 ID 的数据包
    SockAddr.sin_family := AF_INET;
    SockAddr.sin_port := htons(0);
    SockAddr.sin_addr.s_addr := INADDR_ANY;
    if bind(Socket, PSockAddr(@SockAddr)^, SizeOf(SockAddr)) = SOCKET_ERROR then
    begin
        closesocket(Socket);
        WSACleanup;
        Exit;
    end;
    ProcessId := GetCurrentProcessId;
    if setsockopt(Socket, IPPROTO_IP, IP_PKTINFO, PAnsiChar(@ProcessId), SizeOf(ProcessId)) = SOCKET_ERROR then
    begin
        closesocket(Socket);
        WSACleanup;
        Exit;
    end;

    // 加载 RIO 扩展功能表
    if not LoadRioExtensionFunctions(Socket) then
    begin
        closesocket(Socket);
        WSACleanup;
        Exit;
    end;

    // 创建 RIO 完成队列和请求队列
    if not Rio.RIOCreateCompletionQueue(RIO_BUF_SIZE, nil, nil, 0, @CQ) then
    begin
        closesocket(Socket);
        WSACleanup;
        Exit;
    end;
    if not Rio.RIOCreateRequestQueue(CQ, RIO_BUF_SIZE, 1, RIO_BUF_SIZE, 1, nil, nil, nil, @RQ) then
    begin
        Rio.RIOCloseCompletionQueue(CQ);
        closesocket(Socket);
        WSACleanup;
        Exit;
    end;

    // 向 RIO 请求队列中提交接收请求
    for i := 0 to RIO_BUF_SIZE - 1 do
    begin
        Buffer[i].Length := RIO_BUF_SIZE;
        Buffer[i].BufferId := i;
        RioPostRecv(Rio, RQ, @Buffer[i], 1, @RequestContext[i]);
    end;

    // 循环处理网络数据包
    while True do
    begin
        // 等待 RIO 完成队列中有完成的请求
        if Rio.RIOGetCompletionStatusEx(CQ, @Results, RIO_BUF_SIZE, INFINITE, nil) = 0 then
        begin
            Break;
        end;

        // 处理完成请求
        NumEntries := RioGetCompletionStatus(CQ, RIO_BUF_SIZE, 0, INFINITE, @Results);
        for i := 0 to NumEntries - 1 do
        begin
            if Results[i].BytesTransferred > 0 then
            begin
                // 如果是接收请求,则处理接收到的网络数据包
                if Results[i].Type_ = RIO_RECV then
                begin
                    PacketLength := Results[i].BytesTransferred;
                    ProcessPacket(PByte(RequestContext[Results[i].RequestContext]), PacketLength);
                    // 将接收缓冲区重新提交到请求队列,等待下一次接收请求
                    RioPostRecv(Rio, RQ, @Buffer[Results[i].BufferId], 1, RequestContext[Results[i].RequestContext]);
                end;
            end    else begin
                // 如果是发送请求,则处理发送完成事件
                if Results[i].Type_ = RIO_SEND then
                begin
                // 发送完成事件不需要做任何处理
                end;
            end;
        end;
    end;

    // 关闭 RIO 对象和套接字
    Rio.RIOCloseRequestQueue(RQ);
    Rio.RIOCloseCompletionQueue(CQ);
    closesocket(Socket);
    WSACleanup;
end;
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值