Udpcap は、Npcap に基づく受信専用の UDP ソケット エミュレーションです。 Npcap パケット キャプチャ ドライバーを利用してイーサネット トラフィックをキャプチャし、必要なヘッダーをすべて解析して、UDP ペイロードを返します。 Udpcap を使用すると、実際にソケットを開かなくても、UDP ソケットを開いてデータを受信できます。
Npcap も同様に Windows のみを対象としているため、このプロジェクトは 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 ドメインに接続されている場合、問題はさらに悪化するようです。プロセス ハッカーを使用してシステムを調査すると、 System
プロセス (Windows カーネル) が CPU コア全体と同じくらいの量を占有していることがわかります。すべての CPU サイクルを消費するのは常にカーネル内の 1 つのスレッドであり、コール スタックにtcpip.sys
があります。
Windows 10 では、Defender ファイアウォールを無効化できなくなりました。 MpsSvc サービスは、Defender ファイアウォール以外のさらなるセキュリティ機能を提供するため、一時的に非アクティブ化されても実行を継続します。
Windows では、すべての (ユーザー空間で開始された) ネットワーク アクセスで Winsocks/2 API が使用されます。この API はカーネル モード ファイルシステム ドライバーAfd.sys
を使用し、その後トランスポート プロトコル ドライバーtcpip.sys
を使用します。 tcpip.sys ドライバーは、Windows ですべてのプロトコルの魔法が行われる場所です。これは、Windows Defender ファイアウォールがトラフィックを分析するポイントでもあります。 Microsoft は、その目的のためだけに API 全体である Windows Filtering Platform (WFP) を作成しました。この API は Windows Vista 以降で利用できます。 tcpip.sys
の下には、 NDIS.sys
(ネットワーク ドライバー インターフェイス仕様) と実際のイーサネット NIC ドライバーのみが含まれます。したがって、Defender Firewall の 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 ;
}
Udpcap をコンパイルするには、git-for-windows、Visual Studio 2015 以降、および CMake 3.13 以降が必要です。
このリポジトリのクローンを作成します
(あるいは、このリポジトリをアーカイブとしてダウンロードすることもできます。サブモジュールはありません。)
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 のライブラリ タイプを制御します。 STATIC / SHARED / OBJECT に設定できます。設定すると、通常の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
に対してリンクできるようになりました。