http://qs321.pair.com?node_id=11120211

alvise has asked for the wisdom of the Perl Monks concerning the following question:

Good evening Monks, referring to Net::Websocket::Server Perl module, which is the difference between utf8 and binary ?
on_connect => sub { my ($serv, $conn) = @_; $conn->on( }, utf8 => sub { }, binary => sub { },
since whatever I send() to the server, it is always received as utf8, even if I declare type='binary' in the JavaScript socket declaration.

Thanks in advance.

Replies are listed 'Best First'.
Re: Net Websocket Server
by roboticus (Chancellor) on Aug 01, 2020 at 21:24 UTC

    alvise:

    Normally, when I have a question like that, I'll take a look at the test suite for the module. If you look at the t/01_server.t file in the Net::WebSocket::Server distribution, you'll see that it sets up a server in lines 49 through 106 (for version 0.003004-0) and then tests the utf8 callback in lines 150-157 and the binary callback on lines 159-166:

    subtest "echo utf8" => sub { foreach my $msg ("simple", "", ("a" x 32768), "unicode \u2603 snowma +n", "hiragana \u3072\u3089\u304c\u306a null \x00 ctrls \cA \cF \n \e +del \x7f end") { print $sock Protocol::WebSocket::Frame->new(type=>'text', buffer=> +$msg)->to_bytes; my $bytes = _recv($sock => $parser); ok($parser->is_text, "expected text message"); is($bytes, "utf8(" . length($msg) . ") = $msg"); } }; subtest "echo binary" => sub { foreach my $msg ("simple", "", ("a" x 32768), "unicode \u2603 snowma +n", "hiragana \u3072\u3089\u304c\u306a null \x00 ctrls \cA \cF \n \e +del \x7f end", join("", map{chr($_)} 0..255)) { print $sock Protocol::WebSocket::Frame->new(type=>'binary', buffer +=>$msg)->to_bytes; my $bytes = _recv($sock => $parser); ok($parser->is_binary, "expected binary message"); is($bytes, "binary(" . length($msg) . ") = $msg"); } };

    As you can see, the difference is just what type the client requests. If the client requests type=>'text' it looks like it hits the utf8 endpoint, and you get the binary endpoint when requesting type=>'binary'. I didn't dig into it any further, so I don't know what happens if you don't provide a handler for the type the client requests. I'd expect that it would either complain about an illegal request (e.g., "I don't know how to handle type 'foo'") or let it default to binary and let the binary code either figure it out or complain about an illegal binary request.

    Looking at the source code of the module can be helpful, but I frequently find that to be more confusing than looking at the tests: Inside the module, there's a bunch of implementation detail mixed in with the interface, and that can be a bit much to sort through. Looking at the test code, on the other hand, helps you see how to interface with the module without having to trip over the internal implementation details so much. Generally I'll look at the module implementation only if I still have questions after reviewing the test code, and having reviewed the test code, I'll normally have a bit better of an idea of where to look and what to look at.

    If you're getting the same callback when you specify 'binary' in the JavaScript socket declaration, I'd expect that your JavaScript code may be specifying the type='binary' in different location than what the Net::WebSocket::Server code expects, so it doesn't see the type attribute setting.

    I hope this helps!

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

Re: Net Websocket Server (updated)
by haukex (Archbishop) on Aug 02, 2020 at 09:02 UTC

    roboticus explained it from the implementation side, but you can also look to the specification:

    A frame has an associated type. Each frame belonging to the same message contains the same type of data. Broadly speaking, there are types for textual data (which is interpreted as UTF-8 [RFC3629] text), binary data (whose interpretation is left up to the application), and control frames ...

    So Net::WebSocket::Server allows you to specify handlers for the two kinds of data frames.

    Update:

    since whatever I send() to the server, it is always received as utf8, even if I declare type='binary' in the JavaScript socket declaration.

    That would be a JS issue; you haven't shown your JS code and I don't see this "type='binary'" in the WebSocket API. This works fine for me:

    var socket = new WebSocket("ws://localhost:8080"); socket.send("Hello"); // sent as text (UTF-8) socket.send( new Blob(["World"]) ); // sent as binary
      thank you haukex, I didn't think to add "new Blob" to the argument of send(). That solved my problem. Your suggestion is highly useful and appreciated. Regards from Rome, Italy.