WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?

Posted

技术标签:

【中文标题】WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?【英文标题】:How does WSARecv make use of lpOverlapped? How can I manually signal the event? 【发布时间】:2011-08-21 19:51:38 【问题描述】:

我需要弄清楚当 lpCompletionRoutine 为空时 WSARecv 如何使用 lpOverlapped 参数。它表示位于 lpOverlapped 中的事件,对吗?但肯定不止于此。

我正在拦截正常的 WSARecv 调用,以便记录数据包,并且可以很好地捕获数据,但是客户端挂起并等待被告知 recv 操作已完成。我只是不知道真正的 WSARecv 函数如何使用 lpOverlapped 来通知客户端操作已完成。

当 lpOverlapped 被传入 WSARecv 时,lpOverlapped->hEvent 为空。所以我不能简单地做 SetEvent() 或 WSASetEvent()。我可以通过执行 lpOverlapped->hEvent = WSACreateEvent() 之类的操作来创建一个事件,然后设置该事件,客户端似乎仍然不承认它。

感谢任何帮助。

谢谢!

编辑:我为 WSARecv 调用所做的示例

    int proxyWSARecv(int unused, SOCKET s, LPWSABUF recvBuffer, DWORD bufferCount, LPDWORD bytesRecvd, LPDWORD flags,
    LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine)


    WSAOVERLAPPED wsaoverlapped;
    LPWSAOVERLAPPED ourOverlapped = &wsaoverlapped;
    WSADATA wsaData;
    int rc = WSAStartup(MAKEWORD(2, 2), &wsaData);

    int retnVal;

    __asm
        push lpCompletionRoutine
        push ourOverlapped // our replacement lpoverlapped
        push flags
        push bytesRecvd
        push bufferCount
        push recvBuffer
        push s
        call p_WSARecv // real WSARecv
        mov retnVal, EAX
    

    // get overlapped results and log packets here. etc

【问题讨论】:

客户端可能正在使用I/O completion ports? 好吧,除了 lpOverlapped 之外,我正在使用客户端正在使用的所有相同变量。在那种情况下客户不会继续进行吗? (我将更新我的主要帖子以展示我正在做的一个例子) 如果客户端正在使用 I/O 完成端口,他们可能正在使用 GetQueuedCompletionStatus,并且可能会根据返回的 lpOverlapped 值键入自己的处理,而不是仅使用完成键.在这种情况下,覆盖lpOverlapped 将导致失败。您可以做的是保存调用者的 lpOverlapped 结构,并用您自己的内容覆盖它以保留地址。 (如果我在这里没有完全偏离标记,我可能会将其发布为答案) 好的,有没有办法我自己触发 GetQueuedCompletionStatus 的东西?主要的是我需要在游戏解密数据包之前复制整个数据包(以记录它)。如果我使用提供的 lpOverlapped,通常当我看到它时,数据包已经在内存中发生了变化。顺便说一句,我真的很感谢你的 cmets。 你为什么从你的代理程序调用 WSAStartup?主机应用程序不应该为您执行此操作,可能需要不同的版本吗? 【参考方案1】:

在设置重叠结构时,您必须手动创建(然后关闭)事件。该事件由操作系统设置 - 您只需等待或检查它。

如果重叠结构的事件为NULL,仍然可以通过socket本身来等待socket事件。

【讨论】:

啊,我明白了。谢谢。那么客户端可能会挂起,因为它只是监视套接字事件本身?嗯等等,这不可能。我可以创建自己的 lpOverlapped 并很好地使用它,问题是使用我的 WSARecv 调用的客户端不知道 recv 何时完成。另外,不应该已经设置 lpOverlapped ,因为客户端将它传递给 WSARecv (我正在尝试在视频游戏中记录数据包)

以上是关于WSARecv 如何使用 lpOverlapped?如何手动发出事件信号?的主要内容,如果未能解决你的问题,请参考以下文章

IO 完成端口:WSARecv() 是如何工作的?

如何知道完成数据包是针对 WSASend() 还是 WSARecv() 还是 AcceptEx()?

我可以在 IOCP WSARecv 函数中使用 std::string 吗?

WSARecv() 函数使用解析

readv()、writev()、WSARecv()、WSASend()

当目前没有 wsarecv 时,传入数据会发生啥