2

我正在做一个涉及 hooking 的项目WSARecv。我知道如何挂钩这个函数,我的意思是它就像挂钩另一个函数一样。无论如何,困难的部分是何时WSARecv用于执行重叠操作。这个想法是,当应用程序接收到数据以拦截它并可以修改它时,我正在为此使用管道。本机 DLL 将所有数据通过隧道传输到托管“服务器”。这会处理输入等并将其返回到本机 DLL。这适用WSASendsendrecv。然而,困难的部分是应用程序使用重叠套接字时。

所以我需要先接收到的数据才能处理它,这是困难的部分。我该怎么做这样的事情?我想到了这一点,但它们似乎都一团糟:

使用WSARecvWSAOverlapped 调用时:创建一个新线程,使用WaitForSingleObject并传递hEventWSAOverlapped 结构。当事件发出信号时,将数据处理到托管服务器并将数据传递给程序。

使用完成WSARecv例程调用时:创建一个新线程,将对原始函数的调用修改lpOperationCompleted为一个新函数。用于SleepEx将线程置于警报状态。当 OperationCompleted 被调用时,处理数据并将数据传回程序。

我可以发布我的代码,但我没有写,因为这似乎是一个糟糕的解决方案。所以没有真正的意义。

我想不出更好的解决方案,这似乎很可怕,因为当应用程序调用WSARecv很多时(例如,使用重叠套接字来处理大量客户端的大型服务器)它会为每个调用创建一个新线程,这似乎是个坏主意。

那么我该怎么做呢?

4

1 回答 1

4

无需为每个重叠的 IO 调用创建线程。

当使用重叠操作时,它们要么具有关联的事件(您可以放心地忽略)、完成例程,要么与 I/O 完成端口关联。

要处理前两种情况,您应该同时钩住WSARecv()WSAGetOverlappedResult()

如果你需要处理最后一个,你还需要挂钩GetQueuedCompletionStatus()

现在,当你接到对WSARecv()事件的调用时,你没有做任何特别的事情(除了可能保存一些与 相关的信息lpOverlapped,例如缓冲区),并处理其中的数据WSAGetOverlappedResult()(应用程序必须调用它来获取成功/错误和传输的字节数。)

如果存在完成例程,请保存lpOverlappedandlpCompletionRoutine并将您自己的完成例程传递给 real WSARecv()

您的例程应该处理数据并调用原始完成例程。

处理I/O完成端口的情况,有WSARecv()savelpOverlapped和buffers等,在里面GetQueuedCompletionStatus(),调用原来的,如果返回的重叠结构匹配,就处理数据。

您还应该注意,重叠的操作可能会立即完成,在这种情况下,不会发出事件信号,不会调用完成例程,并且(IIRC)IOCP 上没有完成排队。

于 2013-09-01T14:01:50.033 回答