我正在使用WinDivert通过Windows上的透明代理管道连接(TCP和UDP)。这是如何工作的,通过使用像GETTcpTable2这样的函数进行端口到pid查找,然后检查PID是否与代理的PID或其任何子进程匹配或不匹配。如果它们不匹配,它们将通过代理转发,如果它们发生,则数据包不受影响。
我的问题是,是否有安全的方式或安全的持续时间,我可以“缓存”端口到pid查找的结果?每当我收到大量数据包流过时,比如在youtube上观看视频,使用WinDivert的代码突然扼杀了我的所有CPU,我假设这是在收到的每个数据包上进行TcpTable2查找。我可以看到UDP没有真正的安全持续时间,我可以假设它是绑定到端口的相同进程,但这可能与TCP有关吗?
答案 0 :(得分:2)
作为Luis评论的补充,我认为缓存端口到pid查找的应用程序也可以保持对进程的处理(只需通过OpenProcess
)。问题是,如果与进程关联的资源在关闭它的所有句柄之前都不会被释放。这是正常的,因为在您拥有进程的有效句柄之前,您可以在系统中查询各种信息,例如已用内存或时间。因此,您应该定期查看缓存的进程是否被终止以从缓存中清除条目并关闭句柄。
作为替代方案,您可以保留其他信息,例如流程的开始时间,可通过GetProcessTimes
访问。查看缓存以查找进程ID时,您打开进程并控制其开始时间。如果没问题,这是正确的过程,如果没有,过程ID已被重用,你应该从缓存中清除该条目。
第一种方式应该更高效,因为您不必为每个数据包重新打开进程,但是您必须更严格地识别已终止的进程以释放资源,可能使用一个使用{{1的线程一旦终止,所有进程句柄都会被警告。
第二种方式应该更容易实现。
答案 1 :(得分:0)
所以,我最后在这里做的就是使用两个std :: unordered_maps。一个映射用于存储端口号(作为密钥)以及查询TCPTable以查找绑定到端口(密钥)的进程ID的最后一个系统时间(以毫秒为单位)。如果密钥不存在或者最后一次大于当前系统时间加2秒,则需要重新检查TCPTable以重新检查绑定到端口的PID。在我们完成该检查之后,我们更新第二个映射,该映射使用端口#作为键,并返回一个int,表示使用上一个查询中的相关端口找到的PID。为查询提供了2秒的缓存,将CPU使用率从50%以上降至最高3%。