ByteArray for UDP datagram

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

ByteArray for UDP datagram

HilaireFernandes
Hello,

I want to fill a byte array, but this code does not work:

| packet |
packet := ByteArray streamContents: [:str |
        str nextPut: 16r02; "TOSERVER_INIT"
                nextPut: 28; "SER_FMT_VER_HIGHEST_READ"
                uint16: 0; "NETPROTO_COMPRESSION_NONE"
                uint16: 37; "CLIENT_PROTOCOL_VERSION_MIN"
                uint16: 38; "LATEST_PROTOCOL_VERSION"
                nextPutAll: 'Player'. "Player name"
].
 packet contents


nor this variant:

| packet |
packet := OrderedCollection streamContents: [:str |
        str nextPut: 16r02; "TOSERVER_INIT"
                nextPut: 28; "SER_FMT_VER_HIGHEST_READ"
                uint16: 0; "NETPROTO_COMPRESSION_NONE"
                uint16: 37; "CLIENT_PROTOCOL_VERSION_MIN"
                uint16: 38; "LATEST_PROTOCOL_VERSION"
                nextPutAll: 'Player'. "Player name"
].
(ByteArray withAll: packet contents) inspect



Given the packet must to be filled with byte, short, double, string, what is
the best/neat way to prepare packet for datagram?

Thanks

Hilaire




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

Reply | Threaded
Open this post in threaded view
|

Re: ByteArray for UDP datagram

Sven Van Caekenberghe-2
Hilaire,

You should use a character encoder, for example like this:

| packet |
packet := ByteArray streamContents: [:str |
        str nextPut: 16r02; "TOSERVER_INIT"
                nextPut: 28; "SER_FMT_VER_HIGHEST_READ"
                uint16: 0; "NETPROTO_COMPRESSION_NONE"
                uint16: 37; "CLIENT_PROTOCOL_VERSION_MIN"
                uint16: 38; "LATEST_PROTOCOL_VERSION"
                nextPutAll: ('Player' encodeWith: #utf8). "Player name"
].
packet contents.

Note that there are different options:

'Player' encodeWith: #utf8.
'Player' encodeWith: #null.
'Player' encodeWith: #ascii.

But for an ASCII string they give the same result.

#null asZnCharacterEncoder.
#ascii asZnCharacterEncoder.

There is also #utf8Encoded on String.

Sven

> On 16 Jan 2020, at 11:54, HilaireFernandes <[hidden email]> wrote:
>
> | packet |
> packet := ByteArray streamContents: [:str |
> str nextPut: 16r02; "TOSERVER_INIT"
> nextPut: 28; "SER_FMT_VER_HIGHEST_READ"
> uint16: 0; "NETPROTO_COMPRESSION_NONE"
> uint16: 37; "CLIENT_PROTOCOL_VERSION_MIN"
> uint16: 38; "LATEST_PROTOCOL_VERSION"
> nextPutAll: 'Player'. "Player name"
> ].
> packet contents


Reply | Threaded
Open this post in threaded view
|

Re: ByteArray for UDP datagram

HilaireFernandes
Thanks Sven, it works.

If understood correctly ByteArray on streaming only accept ByteArray.
I wonder, should the string be terminated by a null byte, as exepcted on C?

Hilaire



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

Reply | Threaded
Open this post in threaded view
|

Re: ByteArray for UDP datagram

Sven Van Caekenberghe-2


> On 16 Jan 2020, at 12:11, HilaireFernandes <[hidden email]> wrote:
>
> Thanks Sven, it works.
>
> If understood correctly ByteArray on streaming only accept ByteArray.
> I wonder, should the string be terminated by a null byte, as exepcted on C?

That dependents on your protocol's definition/spec.

It is easy to add a null byte,

  stream nextPut: 0

In some protocols, strings are encoded with a byte length prefix.

> Hilaire
>
>
>
> -----
> http://drgeo.eu
> --
> Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
>


Reply | Threaded
Open this post in threaded view
|

Re: ByteArray for UDP datagram

HilaireFernandes
Thanks for the tips.

So far, I've found two ways to write the datagram. One with stream, the
other one with hexadecimal representation.

The former is verbose but helps for the clarity. The latter is shorter while
tricky when variable content need to be inserted in the datagram

Are they better way to write the datagram?

Thanks

Hilaire

--------------------8<----------------------
| server socket packet result |

packet := ByteArray streamContents: [ :str |
        str uint32: 16r4F457403;
                uint16: 0;
                nextPut: 0;
                nextPut: 3;
                uint16: 65500;
                nextPut: 1].
"Shorted but not as readable"
packet := ByteArray readHexFrom: '4F45740300000003FFDC01'.

server := NetNameResolver addressForName: 'localhost'.
socket := Socket newUDP setPort: 30000; yourself.
socket sendUDPData: packet toHost: server port: 30000.
socket waitForDataFor: 1.
packet := ByteArray new: 200.
result := socket receiveUDPDataInto: packet.
result first isZero ifFalse: [
        | peerId |
        peerId := packet unsignedShortAt: 13 bigEndian: true.
        UIManager default inform: 'Connected to Minetest server, peer id: ', peerId
asString.
        "Disconnect"
        packet := ByteArray streamContents: [ :str |
                str uint32: 16r4F457403;
                        uint16: peerId;
                        nextPut: 0;
                        nextPut: 0;
                        nextPut: 3].
        "Shorter but tricky"
        packet := ByteArray readHexFrom: '4F457403', (peerId printStringBase: 16
length: 4 padded: true), '000003'.

        socket sendUDPData: packet toHost: server port: 30000.
        UIManager default inform: 'Disconnected from Minetest server.'.
          ].
socket closeAndDestroy.




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