On UDP broadcast

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
12 messages Options
Reply | Threaded
Open this post in threaded view
|

On UDP broadcast

HilaireFernandes
Hi,

I try to figure out this matter. I am just new to this domain so excuse
me for the obvious the errors.

To broadcast an IP, this seems to work:

| socket |

socket := Socket newUDP.
socket setOption: 'SO_BROADCAST' value: true.
10 timesRepeat: [
     socket sendUDPData: '10.7.2.1'  toHost: #[255 255 255 255] port: 9999.
     (Delay forSeconds: 1) wait.
      ].
socket closeAndDestroy.

Then I can listen from the shell: with: nc -ulk 9999

Now for the listener part, I wrote something like:

| socket data |
socket := Socket newUDP.
socket connectTo: NetNameResolver loopBackAddress port: 9999.
socket waitForConnectionFor: 2.
[data := socket receiveDataTimeout: 5.
data crLog] ensure: [ socket closeAndDestroy]

But I got an error when connecting the socket, the debugger message is:

"InvalidSocketStatusException: Socket status must Unconnected before
opening a new connection"

So far I don't see understand this error. Port 9999 is not in use, and
running again after this error the broadcast code does not lead to an error.

Any idea?

Thanks

Hilaire


--
Dr. Geo
http://drgeo.eu



Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

Sven Van Caekenberghe-2
Hi Hilaire,

Check UDPSocketEchoTest for a good, simple example of using UDP sockets in Pharo.

You should not do #connectTo:port: but just #setPort: and listen.

HTH,

Sven

> On 20 May 2018, at 20:59, Hilaire <[hidden email]> wrote:
>
> Hi,
>
> I try to figure out this matter. I am just new to this domain so excuse me for the obvious the errors.
>
> To broadcast an IP, this seems to work:
>
> | socket |
>
> socket := Socket newUDP.
> socket setOption: 'SO_BROADCAST' value: true.
> 10 timesRepeat: [
>     socket sendUDPData: '10.7.2.1'  toHost: #[255 255 255 255] port: 9999.
>     (Delay forSeconds: 1) wait.
>      ].
> socket closeAndDestroy.
>
> Then I can listen from the shell: with: nc -ulk 9999
>
> Now for the listener part, I wrote something like:
>
> | socket data |
> socket := Socket newUDP.
> socket connectTo: NetNameResolver loopBackAddress port: 9999.
> socket waitForConnectionFor: 2.
> [data := socket receiveDataTimeout: 5.
> data crLog] ensure: [ socket closeAndDestroy]
>
> But I got an error when connecting the socket, the debugger message is:
>
> "InvalidSocketStatusException: Socket status must Unconnected before opening a new connection"
>
> So far I don't see understand this error. Port 9999 is not in use, and running again after this error the broadcast code does not lead to an error.



> Any idea?
>
> Thanks
>
> Hilaire
>
>
> --
> Dr. Geo
> http://drgeo.eu
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

HilaireFernandes
Thanks Sven for the indications.

Of course I already looked at this Test, but I got lost. I looked at it
again, and wrote something like:

    | socket data | socket := Socket newUDP. socket setPort: 9999.
    socket waitForConnectionFor: 2; waitForDataFor: 5 . data := Array
    new: 100.     [socket receiveUDPDataInto: data.     data crLog]
    ensure: [ 'Closing socket' crLog. socket closeAndDestroy]

I do not have error, but a time out.

I broadcast from the Linux shell:

    echo 10.7.2.1 | nc -ub 255.255.255.255 9999

The broadcast itself is fine as I can receive it from another shell:

    nc -ulk 9999

    10.7.2.1

Any idea?

Thanks

Hilaire


Le 20/05/2018 à 21:43, Sven Van Caekenberghe a écrit :
> Hi Hilaire,
>
> Check UDPSocketEchoTest for a good, simple example of using UDP sockets in Pharo.
>
> You should not do #connectTo:port: but just #setPort: and listen.
>
> HTH,
>
> Sven

--
Dr. Geo
http://drgeo.eu



Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

HilaireFernandes
Le 21/05/2018 à 10:56, Hilaire a écrit :
> Of course I already looked at this Test, but I got lost. I looked at
> it again, and wrote something like:

Sorry for the badly formated code.
By the way the exception handler does not work in the code version
bellow. When the ConnectionTimedOut is raised the debugger still show up
and the handler is not executed. Strange.

| socket data |
socket := Socket newUDP.
socket setPort: 9999.
socket waitForDataFor: 5 .
data := Array new: 100.
[[socket receiveUDPDataInto: data.
     data crLog] on: Error do:[ 'Error, closing socket' crLog. socket
closeAndDestroy]]
ensure: [ 'Closing socket' crLog. socket closeAndDestroy].



--
Dr. Geo
http://drgeo.eu



Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

Sven Van Caekenberghe-2
Hilaire,

All this is quite tricky and can be platform dependent.

What works for me (non-broadcast) is the following Pharo code for listening:

socket := Socket newUDP setPort: 9999; yourself.
buffer := ByteArray new: 256.
{ buffer. socket waitForDataFor: 60; receiveUDPDataInto: buffer }.
"socket closeAndDestroy."

And the following terminal code

$ echo ABC | nc -u 127.0.0.1 9999

This is on macOS, latest P7. Make sure to not accidentally leave the socket in use.

I can't get the broadcast sending via nc to work (like your terminal example). The -b nc option on macOS is not related to broadcasting.

But I am sure broadcasting works on my local network.

I am playing with Multicast DNS among other things and it works fine, I can receive/resolve .local names in Pharo.

I think that is what you should do too, use mDNS. Each Mac supports that (and Linux does too, Raspberry Pi's use it frequently).

My mac is called 'prometheus', so it is also known as 'prometheus.local' (like a RPi would be known as 'raspberrypi.local'). The teacher's machine could be called 'teacherpc.local'.

In Pharo you then do an mDNS resolve, in the code that I am working on (still experimental), it goes like this:

NeoSimplifiedDNSClient new useMulticastDNS; addressForName: 'teacherpc.local'.

If all is well, you'll get a SocketAddress back.

If the teacher's machine is running a web server, clients can just connect to it using that address.

All this provided everybody is on the same local subnet, of course.

Doing the networking magic yourself is fun, but might be more work that you expect.

BTW, I believe someone did play with UDP broadcasting before, I just can't remember who/when/where. Maybe Henrik ?

Sven

> On 21 May 2018, at 11:17, Hilaire <[hidden email]> wrote:
>
> Le 21/05/2018 à 10:56, Hilaire a écrit :
>> Of course I already looked at this Test, but I got lost. I looked at it again, and wrote something like:
>
> Sorry for the badly formated code.
> By the way the exception handler does not work in the code version bellow. When the ConnectionTimedOut is raised the debugger still show up and the handler is not executed. Strange.
>
> | socket data |
> socket := Socket newUDP.
> socket setPort: 9999.
> socket waitForDataFor: 5 .
> data := Array new: 100.
> [[socket receiveUDPDataInto: data.
>     data crLog] on: Error do:[ 'Error, closing socket' crLog. socket closeAndDestroy]]
> ensure: [ 'Closing socket' crLog. socket closeAndDestroy].
>
>
>
> --
> Dr. Geo
> http://drgeo.eu
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

Stephan Eggermont-3
Sven Van Caekenberghe <[hidden email]> wrote:.
>
> I can't get the broadcast sending via nc to work (like your terminal
> example). The -b nc option on macOS is not related to broadcasting.

Who’s allowed to broadcast?

Stephan


Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

Sven Van Caekenberghe-2


> On 21 May 2018, at 19:37, Stephan Eggermont <[hidden email]> wrote:
>
> Sven Van Caekenberghe <[hidden email]> wrote:.
>>
>> I can't get the broadcast sending via nc to work (like your terminal
>> example). The -b nc option on macOS is not related to broadcasting.
>
> Who’s allowed to broadcast?

Yes, I vaguely remember that Unix permissions are involved, I just don't know how this works exactly.

> Stephan
>
>


Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

cedreek
Noury did. He sent that on the other thread :

« Just want to point that I did some work late 2017 on UDP sockets including multicast and broadcast. 
The package named 'NetworkExtras' is part of the ReusableBricks repo of my team.
It has some dependencies on other packages. »

It may help. I cc Noury. 

Cheers,

Cédrick 

Le 21 mai 2018 à 20:00, Sven Van Caekenberghe <[hidden email]> a écrit :



On 21 May 2018, at 19:37, Stephan Eggermont <[hidden email]> wrote:

Sven Van Caekenberghe <[hidden email]> wrote:.

I can't get the broadcast sending via nc to work (like your terminal
example). The -b nc option on macOS is not related to broadcasting.

Who’s allowed to broadcast?

Yes, I vaguely remember that Unix permissions are involved, I just don't know how this works exactly.

Stephan




Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

Henrik Sperre Johansen
In reply to this post by HilaireFernandes
HilaireFernandes wrote

> Thanks Sven for the indications.
>
> Of course I already looked at this Test, but I got lost. I looked at it
> again, and wrote something like:
>
>     | socket data | socket := Socket newUDP. socket setPort: 9999.
>     socket waitForConnectionFor: 2; waitForDataFor: 5 . data := Array
>     new: 100.     [socket receiveUDPDataInto: data.     data crLog]
>     ensure: [ 'Closing socket' crLog. socket closeAndDestroy]
>
> I do not have error, but a time out.
>
> Dr. Geo
> http://drgeo.eu

With UDP, there is no connection concept, so I'd reckon
waitForConnectionFor: is what gives you a TimeOut error...

Delete that, only use waitForDataFor: n , put it in a loop (so it won't stop
listening until it receives a request), and you should be fine.

Doesn't quite look like neither server nor client yet, the workflow should
be something like:
1) server (you) starts, listening to port you're using and waitsForData: in
an infinite loop.
2) client (student) starts, sends request to broadcast address/port, then
waitsForData: on the socket it created.
3) broadcast server reads request, generates reply, and sends it to the
originIP/port of the request
4) client receives reply, handles it, and closes socket.

Cheers,
Henry

PS. Why use nc when you already have a working broadcast client in pharo? ;)



--
Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html

Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

Noury Bouraqadi-2
In reply to this post by cedreek
Note that the package includes tests that show that the broadcast working :-)

Thanx Cédrick for the CC.
Noury
On 21 May 2018, at 21:17, Cédrick Béler <[hidden email]> wrote:

Noury did. He sent that on the other thread :

« Just want to point that I did some work late 2017 on UDP sockets including multicast and broadcast. 
The package named 'NetworkExtras' is part of the ReusableBricks repo of my team.
It has some dependencies on other packages. »

It may help. I cc Noury. 

Cheers,

Cédrick 

Le 21 mai 2018 à 20:00, Sven Van Caekenberghe <[hidden email]> a écrit :



On 21 May 2018, at 19:37, Stephan Eggermont <[hidden email]> wrote:

Sven Van Caekenberghe <[hidden email]> wrote:.

I can't get the broadcast sending via nc to work (like your terminal
example). The -b nc option on macOS is not related to broadcasting.

Who’s allowed to broadcast?

Yes, I vaguely remember that Unix permissions are involved, I just don't know how this works exactly.

Stephan





Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

HilaireFernandes
In reply to this post by Henrik Sperre Johansen
Hi Henrik,


Le 22/05/2018 à 10:57, Henrik Sperre Johansen a écrit :
> With UDP, there is no connection concept, so I'd reckon
> waitForConnectionFor: is what gives you a TimeOut error...

The #waitForConnectionFor: message seems not to be the issue. I was
doing something apparently stupid: I started first the broadcast from
the shell, then the listener in Pharo. Funnily I was doing it the other
way when using nc to listen. Any way I will still discard
#waitForConnectionFor:
> Delete that, only use waitForDataFor: n , put it in a loop (so it won't stop
> listening until it receives a request), and you should be fine.
ok

> Doesn't quite look like neither server nor client yet, the workflow should
> be something like:
> 1) server (you) starts, listening to port you're using and waitsForData: in
> an infinite loop.
> 2) client (student) starts, sends request to broadcast address/port, then
> waitsForData: on the socket it created.
> 3) broadcast server reads request, generates reply, and sends it to the
> originIP/port of the request
> 4) client receives reply, handles it, and closes socket.
If I understand correctly what you suggest, student workstations
initiate the broadcast to manifest interest to access

My scenario initial idea was a bit more like:
1) server, teacher workstation, continuously broadcast its IP to a
specific port.
2) student workstation, when they want to access teacher shares, listen
to this port to get the teacher workstation IP
3) once student workstation got the ip, it stops listen for broadcast,
and it connects to the to the teacher workstation http server to access
the shares.

Your scenario does not need a continuously broadcast...

> PS. Why use nc when you already have a working broadcast client in pharo?;)
Oh, just to play with one variable at a time.  But seems I introduced a
human factor.

Thanks

Hilaire


--
Dr. Geo
http://drgeo.eu



Reply | Threaded
Open this post in threaded view
|

Re: On UDP broadcast

HilaireFernandes
In reply to this post by Noury Bouraqadi-2
I took a look of course. Thanks.

At my basic level of knowledge, I found the articles on the Pharo books
and the basic Tests on Socket very helpful.

Hilaire


Le 23/05/2018 à 17:42, N. Bouraqadi a écrit :

> Note that the package includes tests that show that the broadcast
> working :-)
>
> Thanx Cédrick for the CC.
> Noury
>> On 21 May 2018, at 21:17, Cédrick Béler
>> <[hidden email]
>> <mailto:[hidden email]>> wrote:
>>
>> Noury did. He sent that on the other thread :
>>
>> « Just want to point that I did some work late 2017 on UDP sockets
>> including multicast and broadcast.
>> The package named 'NetworkExtras' is part of the ReusableBricks repo
>> of my team.
>> http://smalltalkhub.com/#!/~CAR/ReusableBricks 
>> <http://smalltalkhub.com/#%21/%7ECAR/ReusableBricks>
>> It has some dependencies on other packages. »
>>
>> It may help. I cc Noury.

--
Dr. Geo
http://drgeo.eu