Udpcap 是基于 Npcap 的仅接收 UDP 套接字仿真。它利用 Npcap 数据包捕获驱动程序来捕获以太网流量、解析所有必要的标头并返回 UDP 有效负载。使用 Udpcap,您可以打开 UDP 套接字并接收数据,而无需实际打开套接字!
该项目仅适用于 Windows,因为 Npcap 也仅针对 Windows。
Udpcap可以:
Udpcap不能:
所有依赖项都可以通过 CMake 方便地获取。然而,为了实际使用 Udpcap,需要安装 Npcap 驱动程序。请记住,Npcap 许可证是专有的。
使用数据包捕获驱动程序来模拟 UDP 套接字听起来是一个糟糕的主意,当您可以使用正确的 UDP 套接字时?嗯,可能是这样。但请稍等,该项目可以解决一个非常具体的 Windows 问题。
与 Windows 7 相比,Windows 10 具有更激进的 Windows Defender(MpsSvc 服务)。当在 Windows 10 上使用常规套接字接收许多UDP 多播数据包时,Windows Defender 会导致大量 CPU 负载,从而导致整个系统出现延迟。当 Windows 计算机连接到 Windows 域(大型公司网络中通常这样做)时,问题似乎会更严重。当用Process Hacker调查System时,我们可以看到System
进程(Windows内核)占用了整个CPU核心。它始终是内核中的一个线程耗尽所有 CPU 周期,并且它的调用堆栈中有tcpip.sys
:
Defender 防火墙无法再在 Windows 10 中停用。 MpsSvc 服务甚至在暂时停用时仍会继续运行,因为除了 Defender 防火墙之外,它还提供了更多安全功能。
在 Windows 上,每个(用户空间启动的)网络访问都使用 Winsocks/2 API。该 API 使用内核模式文件系统驱动程序Afd.sys
,然后使用传输协议驱动程序tcpip.sys
。 tcpip.sys 驱动程序是 Windows 中所有协议魔法发生的地方。这也是 Windows Defender 防火墙分析流量的点。 Microsoft 专门为此目的创建了完整的 API:Windows 过滤平台 (WFP)。此 API 在 Windows Vista 及更高版本中可用。 tcpip.sys
下面仅包含NDIS.sys
(网络驱动程序接口规范)和实际的以太网 NIC 驱动程序。因此,要解决 Defender 防火墙 CPU 负载问题,我们需要绕过整个tcpip.sys
驱动程序及其之上的所有内容。请参阅下图(黑线)以获取概述。使用 Npcap 时,Windows Defender 看不到任何打开的套接字,也不会分析流量。然而,这意味着必须在用户空间中重新实现 UDP 协议栈(这就是 Udpcap 派上用场的地方!) 。
Udpcap 有一个非常简单的 API,与其他众所周知的套接字 API 非常相似:
# include < iostream >
# include < udpcap/udpcap_socket.h >
int main ()
{
// Create a Udpcap socket and bind it to a port. For this example we want to
// receive data from any local or remote source and therefore not bind to an
// IP address.
Udpcap::UdpcapSocket socket;
socket. bind ( Udpcap::HostAddress::Any (), 14000 );
for (;;)
{
// Allocate a buffer for the received datagram. The size of the buffer
// should be large enough to hold the largest possible datagram.
std::vector< char > datagram ( 65535 );
// Create an error code object to hold the error code if an error occurs.
Udpcap::Error error = Udpcap::Error::OK;
// Receive a datagram from the Socket. This is a blocking
// operation. The operation will return once a datagram has been received,
// the socket was closed by another thread or an error occured.
size_t num_bytes = socket. receiveDatagram (datagram. data (), datagram. size (), error);
// Resize the buffer to the actual size of the received datagram.
datagram. resize (num_bytes);
std::cout << " Received " << datagram. size () << " bytes: "
<< std::string (datagram. data (), datagram. size ())
<< std::endl;
}
return 0 ;
}
您将需要 git-for-windows、Visual Studio 2015 或更高版本以及 CMake 3.13 或更高版本来编译 Udpcap。
克隆这个仓库
(或者,您可以将此存储库下载为存档。没有子模块。)
git clone https://github.com/eclipse-ecal/udpcap.git
cd udpcap
调用CMakeWindows.bat
这还将下载以下依赖项:
.lib
文件).lib
文件)使用 Visual Studio 打开_build/udpcap.sln
并编译udpcap
和示例
为了查看示例的一些输出,显然您必须始终执行 sender 和 udpcap_reciever 示例。
您可以设置以下 CMake 选项来控制 Udpcap 的构建方式:
选项 | 类型 | 默认 | 解释 |
---|---|---|---|
UDPCAP_BUILD_SAMPLES | BOOL | ON | 构建用于发送和接收虚拟数据的 Udpcap(和 asio)示例 |
UDPCAP_BUILD_TESTS | BOOL | OFF | 构建 udpcap GTest。需要 GTest::GTest 可用。 |
UDPCAP_THIRDPARTY_ENABLED | BOOL | ON | 激活/停用集成依赖项的使用。 |
UDPCAP_THIRDPARTY_USE_BUILTIN_NPCAP | BOOL | ON | 获取并构建 npcap SDK 的集成版本。 仅当 UDPCAP_THIRDPARTY_ENABLED=ON 时可用 |
UDPCAP_THIRDPARTY_USE_BUILTIN_PCAPPLUSPLUS | BOOL | ON | 针对 Pcap++ 的集成版本获取并构建。 仅当 UDPCAP_THIRDPARTY_ENABLED=ON 时可用 |
UDPCAP_THIRDPARTY_USE_BUILTIN_ASIO | BOOL | ON | 获取并构建集成版本的 asio。 仅当 UDPCAP_THIRDPARTY_ENABLED=ON 时可用 |
UDPCAP_THIRDPARTY_USE_BUILTIN_GTEST | BOOL | ON | 针对预定义版本的 GTest 获取并构建测试。如果禁用,则必须从外部提供目标。 仅当 UDPCAP_THIRDPARTY_ENABLED=ON 且UDPCAP_BUILD_TESTS=ON 时可用 |
UDPCAP_LIBRARY_TYPE | STRING | 通过将字符串注入add_library 调用来控制 Udpcap 的库类型。可以设置为静态/共享/对象。如果设置,这将覆盖常规BUILD_SHARED_LIBS CMake 选项。如果未设置,CMake 将使用默认设置,该设置由BUILD_SHARED_LIBS 控制。 |
集成为二进制文件:
下载 udpcap 版本或按照前面所述构建它。如果您自己构建,请确保构建并安装调试版本和发布版本。
如果您选择共享udpcap 库 (-> .dll
),它将是独立的,您只需将udpcap.dll
/ udpcapd.dll
复制到您的应用程序目录即可。
如果您选择静态udpcap 库 (-> .lib
),则还需要使以下目标可用于 CMake:
pcapplusplus::pcapplusplus
npcap::npcap
查看 Udpcap 集成示例以获取有关如何执行此操作的建议。您可以在此处找到用于获取和查找 Npcap 和 Pcap++ 的脚本和模块:
将 udpcap 目录添加到CMAKE_PREFIX_PATH
:
cmake your_command_line -DCMAKE_PREFIX_PATH=path/to/udpcap/install/dir
集成为源
无论哪种方式,都可以使用 udpcap 源。例如,您可以手动下载它、使用 git 子模块或使用 CMake FetchContent。
将以下内容添加到您的CMakeLists.txt
:
# You will probably not need the samples, so turn them off.
set (UDPCAP_BUILD_SAMPLES OFF )
# Add the top-level directory as cmake subdirectory
add_subdirectory ( "path_to_udpcap" )
# Add the dummy Findudpcap.cmake do the module path to make
# find_package(udpcap) succeed.
list ( APPEND CMAKE_MODULE_PATH "path_to_udpcap/thirdparty/udpcap/Modules" )
现在您可以链接udpcap::udpcap