1

Server (crystal)

require "http"

module Network
    class WebSocket < HTTP::WebSocketHandler
        HANDLERS = [] of HTTP::Handler
        def initialize (@path : String, &@proc : HTTP::WebSocket, HTTP::Server::Context -> Nil)
            HANDLERS << self
        end

        def self.run (host : String = "::", port : Int32 = 3030)
            puts "Run server on ws://[#{host}]:#{port}"
            HTTP::Server.new(host, port, HANDLERS).listen
        end
    end
end

Network::WebSocket.new "/" do |socket|
    socket.send("Hello From Binary!".to_slice)
end

Network::WebSocket.run

Client(JavaScript)

ws = new WebSocket("ws://[2a01:4f8:xx:xx::xx]:3030/")
ws.onmessage = (message) => {
    console.log(message.data)
}

Console.log show me ArrayBuffer(13) with byte length and without any payload.

But! Python client (https://github.com/websocket-client/websocket-client) works fine.

from websocket import create_connection
ws = create_connection("ws://[::]:3030")
print("Receiving...")
result =  ws.recv()
print("Received '%s'" % result)
ws.close()

Binary receiving doesn't work in chromium & firefox.

Sorcus
  • 13
  • 2
  • What did you expect to receive instead of an array buffer? you are sending binary data. https://stackoverflow.com/questions/6965107/converting-between-strings-and-arraybuffers – briosheje Nov 28 '17 at 12:20
  • But it doesn't work with `ws.binaryType = "blob"` and `ws.binaryType = "arraybuffer"`. – Sorcus Nov 28 '17 at 12:33
  • The is only way is convert string to ArrayBuffer? Really? What the ...? – Sorcus Nov 28 '17 at 12:48
  • If you're not comfortable with it, convert it to an usigned int array, then do whatever you need with it ;) – briosheje Nov 28 '17 at 13:34

1 Answers1

5

Use ws.binaryType = "arraybuffer" and convert it to Uint8Array on a client:

new Uint8Array(message.data) // => [72, 101, 108, 108, 111, 32, 70, 114, 111, 109, 32, 66, 105, 110, 97, 114, 121, 33]

which matches the byte array sent from Crystal server:

"Hello From Binary!".to_slice # => Bytes[72, 101, 108, 108, 111, 32, 70, 114, 111, 109, 32, 66, 105, 110, 97, 114, 121, 33]
Vitalii Elenhaupt
  • 7,146
  • 3
  • 27
  • 43
  • Oh, you right. It's working. But why console.log(message.data) doesn't show me payload before converting to `Uint8Array`? – Sorcus Nov 28 '17 at 13:05
  • Because you can't [directly manipulate the contents of an ArrayBuffer; instead, you create one of the typed array objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer). I guess it is designed not to display a content, even in a console. – Vitalii Elenhaupt Nov 28 '17 at 13:08