> On 19 May 2015, at 10:53, Udo Schneider <udo.schnei...@homeaddress.de> wrote: > > > Did you look in all your package caches ? > I did. Must have been a victim of cleaning ... but maybe TimeMachine has > something ... thanks for the reminder. > > > If it is just a small example, like one class, maybe it could be > > added to the image, in which case it should indeed be a slice. > The package was pretty simple. Basically only adding a few convenience > methods around Socket>>#setOption:value: . Still I think a usage example in > form of a class comment and test case might be appropriate. So unless > Multicast should be part of the base image I'll start with a separate package > first.
Since Socket is a fundamental part, and multicast is a key feature, I think it would logical to move it to the image itself, with a test case. > CU, > > udo > > > On 19/05/15 10:38, Sven Van Caekenberghe wrote: >> >>> On 19 May 2015, at 10:30, Udo Schneider <udo.schnei...@homeaddress.de> >>> wrote: >>> >>> Hi Sven, >>> >>> you got me :-) >>> >>> I had this as a package sometime ago for my own purposes (mDNS). So I knew >>> it does work and how to do it. It's just I can't find that damned package >>> anymore... >> >> Did you look in all your package caches ? >> >>>> I do think making all this cross platform could be a bit harder, we'll see. >>> It's not that hard. The socket API is the same on all supported platforms. >>> No surprises on *nix based OS. The only exception is Windows where the API >>> is the same but where you might run into some packet drops due to strange >>> personal FW products and "value-add" NDIS drivers for NICs. The situation >>> has gotten much better though since Windows Vista/7 are using multicast for >>> some of their services out of the box. >>> >>> I will recreate it though. Should I simply publish a package or add this as >>> a slice? >> >> Thanks a lot, Udo, a good multicast example would be super cool. >> >> If it is just a small example, like one class, maybe it could be added to >> the image, in which case it should indeed be a slice. >> >> If it is larger and more application/framework oriented, then maybe a >> standalone package is more interesting. We try to keep the image as modular >> as possible. This route would be a bit more work for you, but might make >> more sense if you also see it possibly growing in the future. >> >>> Best Regards, >>> >>> Udo >>> >>> >>> On 19/05/15 10:20, Sven Van Caekenberghe wrote: >>>> Hi Udo, >>>> >>>> It would be good if some of this knowledge could be added inside the >>>> image, as class comment or methods comments. Even better would be an >>>> example combined with a unit test, like UDPSocketEchoTest and >>>> TCPSocketEchoTest - the unit test would then actively ensure this >>>> functionality is protected. >>>> >>>> I do think making all this cross platform could be a bit harder, we'll see. >>>> >>>> Sven >>>> >>>>> On 19 May 2015, at 00:17, Udo Schneider <udo.schnei...@homeaddress.de> >>>>> wrote: >>>>> >>>>> This should have been 'IP_ADD_MEMBERSHIP' of course: >>>>> >>>>> imrMultiaddr := #[239 255 255 250]. >>>>> imrInterface := #[0 0 0 0]. >>>>> ipMreq := imrMultiaddr , imrInterface. >>>>> socket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq. >>>>> >>>>> >>>>> The "server" could be something like this (execute in first playground). >>>>> I used another IP address (#[239 255 255 251]) because #[239 255 255 250] >>>>> might already be part of the multicast group because of other processes >>>>> and this shows the "whole" process of subscribing to a multicast group: >>>>> >>>>> [ >>>>> | udpSocket | >>>>> udpSocket := Socket newUDP. >>>>> udpSocket setPort: 1900. >>>>> imrMultiaddr := #[239 255 255 251]. >>>>> imrInterface := #[0 0 0 0]. >>>>> ipMreq := imrMultiaddr , imrInterface. >>>>> udpSocket setOption: 'IP_ADD_MEMBERSHIP' value: ipMreq. >>>>> udpSocket setOption: 'IP_MULTICAST_LOOP' value: 1. >>>>> "udpSocket setOption: 'SO_REUSEADDR' value: 1." >>>>> udpSocket waitForData. >>>>> buffer := ByteArray new: 256. >>>>> data := udpSocket receiveUDPDataInto: buffer. >>>>> bytesRead := data at: 1. >>>>> sender := data at: 2. >>>>> senderPort := data at: 3. >>>>> more := data at: 4. >>>>> result := buffer copyFrom: 1 to: bytesRead. >>>>> udpSocket closeAndDestroy. >>>>> result asString inspect. >>>>> ] fork. >>>>> >>>>> >>>>> >>>>> The "client" (execute in different playground): >>>>> | 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 251] port: 1900. >>>>> (udpSocket waitForSendDoneFor: 5). >>>>> udpSocket closeAndDestroy. >>>>> >>>>> Hope this helps. >>>>> >>>>> CU, >>>>> >>>>> Udo >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>>> On 18/05/15 23:29, Udo Schneider wrote: >>>>>> Hi Manfred, >>>>>> >>>>>> I just stumbled over the IP address you are using (239.255.255.250). If >>>>>> I remember correctly this is a IPv4 Class D Multicast address. >>>>>> (224.0.0.0-239.255.255.255). >>>>>> >>>>>> So if you want to transmit datagrams to this IP address or recieve >>>>>> datagrams sent to this multicast groups you have to set appropriate IP >>>>>> Options. >>>>>> >>>>>> You can set this options using Socket>>#setOption:value: and read them >>>>>> using Socket>>#getOption:. Please note that both methods expect the >>>>>> option to set as a name - not as constant. E.g. >>>>>> >>>>>> socket setOption: 'IP_MULTICAST_IF' value: multicastInterface. >>>>>> >>>>>> If I do remember correctly you have to set the following options for >>>>>> sending/receiving: >>>>>> >>>>>> Sending: >>>>>> IP_MULTICAST_IF >>>>>> (IP_MULTICAST_LOOP) >>>>>> (IP_MULTICAST_TTL) >>>>>> >>>>>> Sending should AFAIK work w/o setting any option - although >>>>>> IP_MULTICAST_IF is highly recommended. >>>>>> >>>>>> Receiving: >>>>>> (SO_REUSEADDR) >>>>>> IP_ADD_MEMBERSHIP >>>>>> (IP_DROP_MEMBERSHIP) >>>>>> >>>>>> Receiving only works if you joined the multicast group previously. So I >>>>>> assume that you need to do something like this (not tested). >>>>>> >>>>>> imrMultiaddr := #[239 255 255 250]. >>>>>> imrInterface := #[0 0 0 0]. >>>>>> ipMreq := imrMultiaddr , imrInterface. >>>>>> socket setOption: 'MEMBERSHIP' value: ipMreq. >>>>>> >>>>>> Hope this helps. >>>>>> >>>>>> CU, >>>>>> >>>>>> Udo >>>>>> >>>>>> >>>>>> >>>>>> On 18/05/15 16:34, Manfred Kröhnert wrote: >>>>>>> Hi Sven, >>>>>>> >>>>>>> On Mon, May 18, 2015 at 4:14 PM, Sven Van Caekenberghe >>>>>>> <s...@stfx.eu >>>>>>> <mailto:s...@stfx.eu>> wrote: >>>>>>> >>>>>>> >>>>>>> > On 18 May 2015, at 15:47, Manfred Kröhnert >>>>>>> <mkroehner...@googlemail.com >>>>>>> <mailto:mkroehner...@googlemail.com>> wrote: >>>>>>> > >>>>>>> > Hi, >>>>>>> > apparently I am missing something else. >>>>>>> > >>>>>>> > I can find devices when connected to a 'regular' LAN. >>>>>>> > >>>>>>> > However, I have a camera that creates a Wifi accesspoint and >>>>>>> makes itself discoverable via SSDP. >>>>>>> > Once I connect to this accesspoint my computer gets a valid IP >>>>>>> address assigned and the NodeJS code is able to discover the device. >>>>>>> > Unfortunately, the Pharo snippet I posted before does not give me >>>>>>> any results and hangs in Socket>>waitForDataIfClosed: . >>>>>>> > >>>>>>> > Any further ideas? >>>>>>> >>>>>>> Are you sure you restarted the image and your code after switching >>>>>>> networks ? >>>>>>> >>>>>>> >>>>>>> I did not check this before. >>>>>>> But I just downloaded a fresh 40613 image with PharoLauncher and started >>>>>>> it after connecting to the camera accesspoint. >>>>>>> The code snippet freezes there as well. >>>>>>> >>>>>>> Manfred >>>>>> >>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>>> >>>> >>>> >>>> >>> >>> >>> >> >> >> > > >