Exchange data via websockets
Use websockets to send binary messages to the server. The server logs the time taken by the client, as well as the time calculated with the received messages sent by the client.
This commit is contained in:
parent
b12b8765a9
commit
afa1d19dd8
6 changed files with 559 additions and 42 deletions
|
@ -14,5 +14,12 @@ yew = "0.19"
|
|||
console_error_panic_hook = "0.1"
|
||||
log = "0.4"
|
||||
wasm-logger = "0.2"
|
||||
futures = "0.3"
|
||||
gloo-timers = "0.2"
|
||||
gloo-net = "0.2"
|
||||
instant = { version = "0.1", features = [ "wasm-bindgen" ] }
|
||||
wasm-bindgen-futures = "0.4"
|
||||
bincode = "1"
|
||||
yew-router = "0.16"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
tokio = { version = "1", default-features = false, features = ["sync"] }
|
||||
|
|
9
client/src/lib.rs
Normal file
9
client/src/lib.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Duration;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum Message {
|
||||
Start,
|
||||
Stop,
|
||||
Duration(Duration),
|
||||
}
|
|
@ -1,6 +1,58 @@
|
|||
use futures::{
|
||||
stream::{SplitSink, SplitStream},
|
||||
SinkExt, StreamExt,
|
||||
};
|
||||
use gloo_net::websocket::{futures::WebSocket, Message};
|
||||
use gloo_timers::callback::Interval;
|
||||
use instant::Instant;
|
||||
use log::debug;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use wasm_bindgen_futures::spawn_local;
|
||||
use yew::prelude::*;
|
||||
use yew_router::prelude::*;
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, Routable)]
|
||||
pub enum Route {
|
||||
#[at("/")]
|
||||
LockWatch,
|
||||
#[not_found]
|
||||
#[at("/404")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
struct WebSocketHandle {
|
||||
writer: Arc<Mutex<SplitSink<WebSocket, Message>>>,
|
||||
_reader: Arc<Mutex<SplitStream<WebSocket>>>,
|
||||
}
|
||||
|
||||
impl WebSocketHandle {
|
||||
fn connect(url: &str) -> Self {
|
||||
debug!("connecting to websocket `{}`", url);
|
||||
let ws = WebSocket::open(url)
|
||||
.unwrap_or_else(|_| panic!("could not connect to websocket `{}`", url));
|
||||
let (writer, reader) = ws.split();
|
||||
|
||||
Self {
|
||||
writer: Arc::new(Mutex::new(writer)),
|
||||
_reader: Arc::new(Mutex::new(reader)),
|
||||
}
|
||||
}
|
||||
|
||||
fn send(&self, msg: client::Message) {
|
||||
let writer = self.writer.clone();
|
||||
spawn_local(async move {
|
||||
writer
|
||||
.lock()
|
||||
.await
|
||||
.send(Message::Bytes(
|
||||
bincode::serialize(&msg).expect("could not serialize websocket message"),
|
||||
))
|
||||
.await
|
||||
.expect("could not send websocket message");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
enum Msg {
|
||||
Start,
|
||||
|
@ -9,6 +61,7 @@ enum Msg {
|
|||
}
|
||||
|
||||
struct LockWatch {
|
||||
websocket: WebSocketHandle,
|
||||
duration: Option<Instant>,
|
||||
duration_handle: Option<Interval>,
|
||||
}
|
||||
|
@ -38,6 +91,7 @@ impl Component for LockWatch {
|
|||
|
||||
fn create(_ctx: &Context<Self>) -> Self {
|
||||
Self {
|
||||
websocket: WebSocketHandle::connect("ws://localhost:3000/api/ws"),
|
||||
duration: None,
|
||||
duration_handle: None,
|
||||
}
|
||||
|
@ -47,6 +101,8 @@ impl Component for LockWatch {
|
|||
match msg {
|
||||
Msg::Start => {
|
||||
self.duration = Some(Instant::now());
|
||||
self.websocket.send(client::Message::Start);
|
||||
|
||||
self.duration_handle = {
|
||||
let link = ctx.link().clone();
|
||||
Some(Interval::new(1, move || {
|
||||
|
@ -54,7 +110,12 @@ impl Component for LockWatch {
|
|||
}))
|
||||
};
|
||||
}
|
||||
Msg::Stop => self.duration_handle = None,
|
||||
Msg::Stop => {
|
||||
self.duration_handle = None;
|
||||
self.websocket.send(client::Message::Stop);
|
||||
let duration = self.duration.expect("could not get duration").elapsed();
|
||||
self.websocket.send(client::Message::Duration(duration));
|
||||
}
|
||||
Msg::UpdateDuration => {}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue