Use websockets to exchange data
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
73d3d739e0
commit
6aa9bb0e43
6 changed files with 527 additions and 5 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