Thanks for the explanation. Best, Manfred On Mon, May 18, 2015 at 12:49 PM, Sven Van Caekenberghe <sven@stfx.eu> wrote:
On 18 May 2015, at 12:44, Manfred Kröhnert <mkroehnert42@googlemail.com> wrote:
Hello Sven,
thanks for your fast reply.
On Mon, May 18, 2015 at 11:41 AM, Sven Van Caekenberghe <sven@stfx.eu> wrote: Hi Manfred,
Did you see/study the example/test UDPSocketEchoTest ?
unfortunately I did not see this class, yet. But I did look at the Socket class itself and Socket>>timeTestUDP (in Pharo3).
We removed #timeTestUDP in Pharo 4 and higher, I believe, and replaced it with proper tests/examples.
Also, UDP is very primitive: it is send and forget, returns no errors, and is totally asynchronous. Listening should best be done in a separate process.
Yes, UDP is primitive but the SSDP specification requires using UDP.
Here is how I would write your send part:
| message udpSocket | message := String crlf join: #( 'M-SEARCH * HTTP/1.1' 'HOST:239.255.255.250:1900' 'MAN:"ssdp:discover' 'ST:ssdp:all' 'MX:1' '').
udpSocket := Socket newUDP. udpSocket sendData: message toHost: #[239 255 255 250] port: 1900. udpSocket waitForSendDoneFor: 5. udpSocket closeAndDestroy.
Thanks for this snippet. For some reasons I do not understand yet, this gives me the expected result in contrast to my own version.
I modified it like this to print the results on the Transcript:
| message udpSocket | message := String crlf join: #( 'M-SEARCH * HTTP/1.1' 'HOST:239.255.255.250:1900' 'MAN:"ssdp:discover"' 'ST:ssdp:all' 'MX:1' '').
udpSocket := Socket newUDP. udpSocket sendData: message toHost: #[239 255 255 250] port: 1900. udpSocket waitForSendDoneFor: 5. udpSocket waitForData. [udpSocket dataAvailable ] whileTrue: [ | buffer | buffer := ByteArray new: 1024. udpSocket receiveUDPDataInto: buffer. Transcript show: 'Received: ', buffer. [udpSocket waitForDataFor: 1] on: Error do: [ ]. ]. udpSocket closeAndDestroy.
Currently, this will work for me, since I am not interested in continuously detecting new devices. But you mentioned reading should in general be done in a separate process. Would you reuse the existing udpSocket instance in this case or create a separate one for reading?
I think if it is only for a one time use, it is OK like you are doing it.
Maybe nothing came back because the line ends where wrong ?
The lineendings I used are required by the SSDP specification.
I meant that writing '\r\n' has no effect in Pharo, this is not processed (you could do this manually, of course). This is why I did it with the #join:
That is the difference and why it works now, I guess.
HTH,
Sven
Thanks, Manfred
On 18 May 2015, at 11:29, Manfred Kröhnert < mkroehnert42@googlemail.com> wrote:
Hello everyone,
I am currently trying to get a list of UPnP device via SSDP (Simple Service Discovery Protocol).
A minimalistic working NodeJS example looks like this:
var dgram = require('dgram'); var message = new Buffer( "M-SEARCH * HTTP/1.1\r\n" + "HOST:239.255.255.250:1900\r\n" + "MAN:\"ssdp:discover\"\r\n" + "ST:ssdp:all\r\n" + "MX:1\r\n" + "\r\n" );
var client = dgram.createSocket("udp4");
client.on("message", function (msg, rinfo) { console.log("server got: " + msg + " from " + rinfo.address + ":" + rinfo.port); }); client.send(message, 0, message.length, 1900, "239.255.255.250"); client.close();
I tried to recreate the same functionality in Pharo with the following piece of code:
| message udpSocket host | message := 'M-SEARCH * HTTP/1.1\r\n' , 'HOST:239.255.255.250:1900\r\n' , 'MAN:"ssdp:discover"\r\n' , 'ST:ssdp:all\r\n' , 'MX:1\r\n' , '\r\n'.
udpSocket := Socket newUDP. host := (NetNameResolver addressFromString: '239.255.255.250'). udpSocket sendData: message toHost: host port: 1900. "udpSocket waitForData." Transcript show: 'Received: ' , udpSocket receiveData. udpSocket closeAndDestroy.
Unfortunately, this script hangs both in Pharo3 and Pharo4 (OS X 10.10, Pharo 30856 and 40611). When I interrupt with Cmd+. the debugger shows the method Socket>>waitForDataIfClosed: and the hang is apparently in the line self readSemaphore wait
Could anyone give me some advice if I should to do this differently or what the issue with the Pharo script is?
Thanks in advance, Manfred