📜 ⬆️ ⬇️

Search for devices on the network by SSDP using Poco

In this small example note, I will describe how to find devices on the network using the Simple Service Discovery Protocol ( SSDP ) using the Poco C ++ library.

I agree that the paid full version of Poco includes classes for UpnP work. But for my purposes, the basic version of Poco, which is already able to work with UDP, was quite enough.

On account of the SSDP protocol, it is rather old; the only normal documentation I could find on it was a draft of the official specification . With quite a lot of small letters. ;-)

The essence of the protocol is as follows:
')
Send a broadcast (broadcast) request - UDP packet to the address 239.255.255.250, destination port 1900.

The request body (package) can be viewed in the source code. I will make a reservation that the only field, the value of which is probably necessary for me is ST: it indicates the type of devices from which we want to get an answer.

Since this is a UDP protocol, there is no guaranteed response as you could get used to when working with HTTP. HTTP works on a request-response basis.

In our case, just all devices that announce themselves to the network, send a UDP packet in response to the address from which the request was sent, IMPORTANT, the answer does not come to port 1900, but to the port from which the request was sent (Source Port).

Since UPD makes no guarantees other than the integrity of the packages themselves. Then for 3 seconds we will listen to the Socket (port) from which the request was sent.

We collect all the answers, and then parse the answers using regular expressions from the same Poco library.

There is another option, just listen to MulticastSocket, this option is given in the Poco documentation on page 17.
But it did not suit me, since the device I was looking for did not announce itself to the network.

In the request, the ST field can take the values:


This is for searching all devices. In my case, here I indicate a specific class of devices from which I want to receive. But for the article I left upnp: rootdevice

I also make a reservation that C ++ is a new language for me.

So:

#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; } 

Source: https://habr.com/ru/post/328726/


All Articles