我正在开展涉及挂钩WSARecv
的项目。我知道如何挂钩这个函数,我的意思是它与挂钩另一个函数一样。无论如何,困难的部分是当WSARecv
用于执行重叠操作时。这个想法是,当一个应用程序接收数据来拦截它并且可以修改它时,我正在使用管道。本机DLL将所有数据隧道传送到托管“服务器”。这将处理输入等并将其返回到本机DLL。这适用于WSASend
,send
和recv
。然而,困难的部分是当应用程序使用重叠套接字时。
所以我需要先收到的数据才能处理,这是很难的部分。我该怎么办?我想到了这一点,但它们看起来都像是一团糟:
使用WSAOverlapped调用WSARecv
时:
创建一个新线程,使用WaitForSingleObject
并传递WSAOverlapped结构的hEvent
。当事件发出信号时,将数据处理到受管服务器并将数据传递给程序。
使用完成例程调用WSARecv
时:
创建一个新线程,使用lpOperationCompleted
将对原始函数的调用修改为新函数。使用SleepEx
将线程置于可警告状态。当调用OperationCompleted处理数据并将数据传递回程序时。
我可以发布我的代码,但我没有写,因为它似乎是一个糟糕的解决方案..所以没有真正的重点。
我无法想到更好的解决方案,这看起来很糟糕,因为当应用程序调用{{1}}很多时(例如使用重叠套接字处理大量客户端的大型服务器),它会为每个调用创建一个新线程,这似乎是一个坏主意。
那我该怎么做呢?
答案 0 :(得分:4)
无需为每个重叠的IO调用创建一个线程。
当使用重叠操作时,它们要么具有关联事件(您可以放心地忽略),完成例程,要么与I / O完成端口关联。
要处理前两种情况,您应该同时挂钩WSARecv()
和WSAGetOverlappedResult()
。
如果你需要处理最后一个,你还需要挂钩GetQueuedCompletionStatus()
现在,当你接到WSARecv()
的调用时,对于事件情况,你没有做任何特别的事情(除了可能保存一些与lpOverlapped
有关的信息,例如缓冲区),以及处理WSAGetOverlappedResult()
中的数据(应用程序必须调用该数据才能获得成功/错误和传输的字节。)
如果存在完成例程,请保存lpOverlapped
和lpCompletionRoutine
,并将您自己的完成例程传递给真实的WSARecv()
。
您的例程应处理数据并调用原始完成例程。
要处理I / O完成端口的情况,请在WSARecv()
中lpOverlapped
保存GetQueuedCompletionStatus()
和缓冲区等,调用原始文件,如果返回的重叠结构匹配,则处理数据。
您还应注意,重叠操作可能会立即完成,在这种情况下,不会发出事件信号,不会调用完成例程,并且(IIRC)IOCP上没有完成排队。