Pocoを使用してSSDPでネットワーク上のデバイスを検索する

この小さなメモの例では、C ++のPocoライブラリを使用して、Simple Service Discovery Protocol( SSDP )を使用してネットワーク上のデバイスを見つける方法を説明します。



Pocoの有料フルバージョンには、UpnPを操作するためのクラスが含まれると言います。 しかし、私の目的では、UDPの操作方法を既に知っているPocoの基本バージョンで十分でした。



SSDPプロトコルを犠牲にして非常に古く、私が見つけることができた唯一の通常のドキュメントは公式仕様のドラフトでした 。 かなりたくさんの手紙で。 ;-)



プロトコルの本質は次のとおりです。



ネットワークにブロードキャスト要求を送信します-239.255.255.250のUDPパケット、宛先ポート1900。



リクエストの本文(パッケージ)は、ソースコードで表示できます。 値を持っている唯一のフィールドがSTであるという予約を行います。これは、回答を取得したいデバイスのタイプを示します。



これはUDPプロトコルであるため、HTTPで作業するときに慣れる可能性があるため、ここでは保証された答えはありません。 HTTPは要求と応答に基づいて機能します。



この場合、単にネットワークに自分自身をアナウンスするすべてのデバイスは、リクエストの送信元アドレスに応答してUDPパケットを送信します。



UPDは、パッケージ自体の整合性以外の保証は行いません。 その後、3秒間、要求の送信元のソケット(ポート)をリッスンします。



すべての回答を収集してから、同じPocoライブラリの正規表現を使用して回答を解析します。



MulticastSocketをリッスンするだけの別のオプションがあります。このオプションは、17ページのPocoのドキュメントに記載されています。

しかし、私が探していたデバイスがネットワーク上でアナウンスしなかったため、彼は私には向いていませんでした。



要求では、STフィールドは次の値を取ることができます。





これは、すべてのデバイスを見つけるためのものです。 私の場合、ここで受信したいデバイスの特定のクラスを示します。 しかし、記事のために、私はupnpを残しました:rootdevice



また、C ++が私にとって新しい言語であることを予約してください。



だから:



#include <iostream> #include "Poco/Net/DatagramSocket.h" #include "Poco/Net/SocketAddress.h" #include "Poco/Timespan.h" #include "Poco/Exception.h" #include "Poco/RegularExpression.h" #include "Poco/String.h" using std::string; using std::vector; using std::cin; using std::cout; using std::endl; using Poco::Net::SocketAddress; using Poco::Net::DatagramSocket; using Poco::Timespan; using Poco::RegularExpression; void MakeSsdpRequest(vector<string>& responses,string st = "") { if (st.empty()) st = "upnp:rootdevice"; //if (st.empty()) st = "ssdp:all"; string message = "M-SEARCH * HTTP/1.1\r\n" "HOST: 239.255.255.250:1900\r\n" "ST:" + st + "\r\n" "MAN: \"ssdp:discover\"\r\n" "MX:1\r\n\r\n"; DatagramSocket dgs; SocketAddress destAddress("239.255.255.250", 1900); dgs.sendTo(message.data(), message.size(), destAddress); dgs.setSendTimeout(Timespan(1, 0)); dgs.setReceiveTimeout(Timespan(3, 0)); char buffer[1024]; try { //     ,     timeout.     1000 ,  ,  -   , timeout  . for (int i = 0; i < 1000; i++) { int n = dgs.receiveBytes(buffer, sizeof(buffer)); buffer[n] = '\0'; responses.push_back(string(buffer)); } } catch (const Poco::TimeoutException &) { } } string ParseIP(string str) { try { RegularExpression re("(location:.*://)([a-zA-Z_0-9\\.]*)([:/])", RegularExpression::RE_CASELESS); vector<string> vec; re.split(str, 0, vec); if (vec.size() > 2) return vec[2]; } catch (const Poco::RegularExpressionException&) { cout << "RegularExpressionException" << endl; } return ""; } int main() { vector<string> ips, responses; MakeSsdpRequest(responses); for (string response : responses) { //   . if (response.find("HTTP/1.1 200 OK", 0) == 0) { string ip = ParseIP(response); if (!ip.empty()) ips.push_back(ip); } } sort(ips.begin(), ips.end()); ips.erase(unique(ips.begin(), ips.end()), ips.end()); for (const string& ip : ips) { cout << "IP: " << ip << endl; } cout << "Press Enter" << endl; cin.get(); return 0; }
      
      






All Articles