From a521c9012c9ace37dff42d231026d1a75249201d Mon Sep 17 00:00:00 2001 From: Michael Kefeder Date: Tue, 28 Apr 2020 20:16:54 +0200 Subject: [PATCH] Websockets binary msgs (#2109) * info how to run webserver with non-EOL python3 * example how to send and receive binary messages over websockets --- examples/websockets/Cargo.toml | 5 ++++ examples/websockets/README.md | 3 ++- examples/websockets/src/lib.rs | 49 +++++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/examples/websockets/Cargo.toml b/examples/websockets/Cargo.toml index 2911d55a..05adc706 100644 --- a/examples/websockets/Cargo.toml +++ b/examples/websockets/Cargo.toml @@ -9,11 +9,16 @@ crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2.60" +js-sys = "0.3" [dependencies.web-sys] version = "0.3.22" features = [ + "BinaryType", + "Blob", "ErrorEvent", + "FileReader", "MessageEvent", + "ProgressEvent", "WebSocket", ] diff --git a/examples/websockets/README.md b/examples/websockets/README.md index caae8698..ef53dfc7 100644 --- a/examples/websockets/README.md +++ b/examples/websockets/README.md @@ -19,5 +19,6 @@ Then serve the statics and navigate to `host:port` http # or use python -python -m SimpleHTTPServer +python2 -m SimpleHTTPServer +python3 -m http.server ``` diff --git a/examples/websockets/src/lib.rs b/examples/websockets/src/lib.rs index 29703305..d5bf72f5 100644 --- a/examples/websockets/src/lib.rs +++ b/examples/websockets/src/lib.rs @@ -16,15 +16,45 @@ extern "C" { pub fn start_websocket() -> Result<(), JsValue> { // Connect to an echo server let ws = WebSocket::new("wss://echo.websocket.org")?; - + // For small binary messages, like CBOR, Arraybuffer is more efficient than Blob handling + ws.set_binary_type(web_sys::BinaryType::Arraybuffer); // create callback + let cloned_ws = ws.clone(); let onmessage_callback = Closure::wrap(Box::new(move |e: MessageEvent| { - // handle message - let response = e - .data() - .as_string() - .expect("Can't convert received data to a string"); - console_log!("message event, received data: {:?}", response); + // Handle difference Text/Binary,... + if let Ok(abuf) = e.data().dyn_into::() { + console_log!("message event, received arraybuffer: {:?}", abuf); + let array = js_sys::Uint8Array::new(&abuf); + let len = array.byte_length() as usize; + console_log!("Arraybuffer received {}bytes: {:?}", len, array.to_vec()); + // here you can for example use Serde Deserialize decode the message + // for demo purposes we switch back to Blob-type and send off another binary message + cloned_ws.set_binary_type(web_sys::BinaryType::Blob); + match cloned_ws.send_with_u8_array(&vec![5, 6, 7, 8]) { + Ok(_) => console_log!("binary message successfully sent"), + Err(err) => console_log!("error sending message: {:?}", err), + } + } else if let Ok(blob) = e.data().dyn_into::() { + console_log!("message event, received blob: {:?}", blob); + // better alternative to juggling with FileReader is to use https://crates.io/crates/gloo-file + let fr = web_sys::FileReader::new().unwrap(); + let fr_c = fr.clone(); + // create onLoadEnd callback + let onloadend_cb = Closure::wrap(Box::new(move |_e: web_sys::ProgressEvent| { + let array = js_sys::Uint8Array::new(&fr_c.result().unwrap()); + let len = array.byte_length() as usize; + console_log!("Blob received {}bytes: {:?}", len, array.to_vec()); + // here you can for example use the received image/png data + }) + as Box); + fr.set_onloadend(Some(onloadend_cb.as_ref().unchecked_ref())); + fr.read_as_array_buffer(&blob).expect("blob not readable"); + onloadend_cb.forget(); + } else if let Ok(txt) = e.data().dyn_into::() { + console_log!("message event, received Text: {:?}", txt); + } else { + console_log!("message event, received Unknown: {:?}", e.data()); + } }) as Box); // set message event handler on WebSocket ws.set_onmessage(Some(onmessage_callback.as_ref().unchecked_ref())); @@ -44,6 +74,11 @@ pub fn start_websocket() -> Result<(), JsValue> { Ok(_) => console_log!("message successfully sent"), Err(err) => console_log!("error sending message: {:?}", err), } + // send off binary message + match cloned_ws.send_with_u8_array(&vec![0, 1, 2, 3]) { + Ok(_) => console_log!("binary message successfully sent"), + Err(err) => console_log!("error sending message: {:?}", err), + } }) as Box); ws.set_onopen(Some(onopen_callback.as_ref().unchecked_ref())); onopen_callback.forget();