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