> On 21 Oct 2014, at 15:29, Luc Fabresse <luc.fabre...@gmail.com> wrote: > > > yes examples are good. > but I also suggest to use a stream on a UDPSocket instead of manipulating the > socket directly in the model code. > Usually, it lowers the code complexity.
Hmm, are you sure that is even possible with UDP sockets ? I have never seen that ... > Luc > > 2014-10-21 10:36 GMT+02:00 Sven Van Caekenberghe <s...@stfx.eu>: > OK good. > > I think it would be best to add some examples to the image: > > https://pharo.fogbugz.com/f/cases/14275/Add-some-decent-TCP-UDP-examples-and-tests > > I will do that in the coming days. > > > On 21 Oct 2014, at 10:20, Annick Fron <l...@afceurope.com> wrote: > > > > OK super, this example works. I got confused because I did not understand > > that you had 2 variables, buffer passed as argument and result as return. > > > > Annick > > Le 21 oct. 2014 à 09:53, Sven Van Caekenberghe <s...@stfx.eu> a écrit : > > > >> The buffer that you supply to #receiveUDPDataInto: is either a String or a > >> ByteArray, preallocated to a certain size. It gets filled with the > >> incoming data part of the datagram. It should be large enough, it never > >> overflows, if it is too small, you simply miss data (it is lost). If you > >> preallocate N bytes, the result, the incoming data, might be less. > >> > >> The result from #receiveUDPDataInto: is a 4 element array, that I > >> described before. The fields you are looking for are in the second (the ip > >> address of the sender, a 4 element byte array) and in third (the port of > >> the sender) slot. The first element is the actual number of bytes read. > >> You need to copy from 1 to that size out of the buffer. > >> > >> The other fields that are in a datagram, outside the user data, are not > >> accessible. You don't need them, unless you are implementing a TCP/IP > >> stack yourself. > >> > >> Did you try this example ? > >> > >> "An UDP echo server on port 6666" > >> [ Socket newUDP in: [ :socket | > >> | loop buffer result input | > >> buffer := String new: 256. > >> loop := true. > >> socket setPort: 6666. > >> [ loop ] whileTrue: [ > >> [ result := socket receiveUDPDataInto: buffer. > >> result first > 0 ] whileFalse: [ (Delay forMilliseconds: 10) wait ]. > >> input := buffer copyFrom: 1 to: result first. > >> socket sendUDPData: input toHost: result second port: result third. > >> (input beginsWith: #quit) ifTrue: [ loop := false ] ]. > >> socket closeAndDestroy ] ] forkAt: Processor userBackgroundPriority > >> named: 'UDP echo server'. > >> > >> "Any message sent gets echoed back" > >> Socket newUDP in: [ :socket | > >> | buffer result | > >> socket sendUDPData: 'testing ', 99 atRandom asString toHost: > >> NetNameResolver localHostAddress port: 6666. > >> buffer := String new: 256. > >> [ result := socket receiveUDPDataInto: buffer. > >> result first > 0 ] whileFalse: [ (Delay forMilliseconds: 10) wait ]. > >> socket closeAndDestroy. > >> { result. buffer. buffer copyFrom: 1 to: result first } ]. > >> > >> "Send quit to stop the server" > >> Socket newUDP in: [ :socket | > >> | buffer result | > >> socket sendUDPData: 'quit' toHost: NetNameResolver localHostAddress port: > >> 6666. > >> buffer := String new: 256. > >> [ result := socket receiveUDPDataInto: buffer. > >> result first > 0 ] whileFalse: [ (Delay forMilliseconds: 10) wait ]. > >> socket closeAndDestroy. > >> { result. buffer. buffer copyFrom: 1 to: result first } ]. > >> > >> In a terminal (OSX or Linux), you can send a message like this: > >> > >> $ nc -u 127.0.0.1 6666 > >> foo bar > >> foo bar > >> quit > >> quit > >> > >>> On 21 Oct 2014, at 09:31, Annick Fron <l...@afceurope.com> wrote: > >>> > >>> Sven, > >>> > >>> I have put a halt in your sync method, but receiveUDPData comes with 64 > >>> bytes in your app, whereas you have provisioned 48 bytes. > >>> So since you start data at 33, I guess what you receive is the usual > >>> datagram IP header on 16 bytes, then the UDP header on 16 bytes. > >>> http://fr.wikipedia.org/wiki/Internet_Protocol#mediaviewer/File:Ipv4_header.svg > >>> http://fr.wikipedia.org/wiki/User_Datagram_Protocol > >>> > >>> If this is correct, I should see the source IP address on 4 bytes > >>> starting at byte 9, and the total length should be on 4 bytes starting at > >>> byte 5, and not at byte 1. > >>> > >>> Annick > >>> > >>> Le 20 oct. 2014 à 17:29, Sven Van Caekenberghe <s...@stfx.eu> a écrit : > >>> > >>>> Annick, > >>>> > >>>>> On 20 Oct 2014, at 17:12, Annick Fron <l...@afceurope.com> wrote: > >>>>> > >>>>> Thank you but your explanation does not explain what is the type > >>>>> (signed unsigned) and the size of each header component. > >>>>> Thus it is impossible to work with that. > >>>> > >>>> I think you are making this way more difficult than it is. > >>>> > >>>> ZTimestampSNTPClient>>#sync contains a simple, runnable example of using > >>>> datagrams (with a busy wait blocking the calling thread, which is only > >>>> good for something simple, because normally datagrams are asynchronous, > >>>> but that is another story). > >>>> > >>>> What you get back from #receiveUDPDataInto: is an Array with 4 elements: > >>>> > >>>> - number of bytes received, Integer > >>>> - address of sender, ByteArray (use NetNameResolver if necessary) > >>>> - port of sender, Integer > >>>> - whether more datagrams are available for reading, Boolean > >>>> > >>>> The data is in the reallocated buffer that you supplied, > >>>> aStringOrByteArray. > >>>> > >>>> This is all perfectly useable at the Pharo level. > >>>> > >>>> The question about signed/unsigned sounds like a C question, for which > >>>> this is the wrong list, no ? I am sure it is quite easy to find C code > >>>> that works with datagrams on your platform. A byte array is an unsigned > >>>> char array as far as I remember ... > >>>> > >>>> What you put inside the datagram, is up to you and your application. > >>>> > >>>> HTH, > >>>> > >>>> Sven > >>>> > >>>>> Annick > >>>>> > >>>>> Le 17 oct. 2014 à 19:09, Sven Van Caekenberghe <s...@stfx.eu> a écrit : > >>>>> > >>>>>> Yes, you have to use the methods in the protocol 'datagrams' of Socket. > >>>>>> > >>>>>> When you receive a datagram, the IP:PORT of the other party is > >>>>>> included, see #receiveUDPDataInto:'c comment. > >>>>>> > >>>>>> It is all a bit low level, but it works well. > >>>>>> > >>>>>> On 17 Oct 2014, at 18:15, Annick Fron <l...@afceurope.com> wrote: > >>>>>> > >>>>>>> Thank you, but I am confused. > >>>>>>> I have checked your NTP code, and it uses > >>>>>>> sendUDPData and not sendData. Same for receiveUDPData. > >>>>>>> Besides how is it possible to know where the message comes from in a > >>>>>>> broadcast mode ?? > >>>>>>> Annick > >>>>>>> Le 17 oct. 2014 à 17:35, Sven Van Caekenberghe <s...@stfx.eu> a écrit > >>>>>>> : > >>>>>>> > >>>>>>>> UDP is pretty easy, just send and receive byte arrays basically, > >>>>>>>> mostly non-blocking. > >>>>>>>> > >>>>>>>> http://forum.world.st/UDP-Listener-example-td4362851.html > >>>>>>>> http://forum.world.st/SysLogSender-UDP-td4745862.html > >>>>>>>> > >>>>>>>> The API is all in Socket. > >>>>>>>> > >>>>>>>> On 17 Oct 2014, at 17:09, Annick Fron <l...@afceurope.com> wrote: > >>>>>>>> > >>>>>>>>> Hi, > >>>>>>>>> > >>>>>>>>> I was not able to find a UDP example in pharo. > >>>>>>>>> > >>>>>>>>> There are only TCP examples. > >>>>>>>>> > >>>>>>>>> Any pointer ? > >>>>>>>>> > >>>>>>>>> Annick > >>>>>>>>> > >>>>>>>> > >>>>>>>> > >>>>>>> > >>>>>> > >>>>> > >>>> > >>> > >> > > > > >