//! Simple websocket client. use std::time::Duration; use std::{io, thread}; use actix::io::SinkWrite; use actix::*; use actix_codec::{AsyncRead, AsyncWrite, Framed}; use awc::{ error::WsProtocolError, ws::{Codec, Frame, Message}, Client, }; use bytes::Bytes; use futures::stream::{SplitSink, StreamExt}; #[actix_rt::main] async fn main() { ::std::env::set_var("RUST_LOG", "actix_web=info"); env_logger::init(); let (response, framed) = Client::new() .ws("http://127.0.0.1:8080/ws/") .connect() .await .map_err(|e| { println!("Error: {}", e); }) .unwrap(); println!("{:?}", response); let (sink, stream) = framed.split(); let addr = ChatClient::create(|ctx| { ChatClient::add_stream(stream, ctx); ChatClient(SinkWrite::new(sink, ctx)) }); // start console loop thread::spawn(move || loop { let mut cmd = String::new(); if io::stdin().read_line(&mut cmd).is_err() { println!("error"); return; } addr.do_send(ClientCommand(cmd)); }); } struct ChatClient(SinkWrite, Message>>) where T: AsyncRead + AsyncWrite; #[derive(Message)] #[rtype(result = "()")] struct ClientCommand(String); impl Actor for ChatClient where T: AsyncRead + AsyncWrite, { type Context = Context; fn started(&mut self, ctx: &mut Context) { // start heartbeats otherwise server will disconnect after 10 seconds self.hb(ctx) } fn stopped(&mut self, _: &mut Context) { println!("Disconnected"); // Stop application on disconnect System::current().stop(); } } impl ChatClient where T: AsyncRead + AsyncWrite, { fn hb(&self, ctx: &mut Context) { ctx.run_later(Duration::new(1, 0), |act, ctx| { act.0.write(Message::Ping(Bytes::from_static(b""))).unwrap(); act.hb(ctx); // client should also check for a timeout here, similar to the // server code }); } } /// Handle stdin commands impl Handler for ChatClient where T: AsyncRead + AsyncWrite, { type Result = (); fn handle(&mut self, msg: ClientCommand, _ctx: &mut Context) { self.0.write(Message::Text(msg.0)).unwrap(); } } /// Handle server websocket messages impl StreamHandler> for ChatClient where T: AsyncRead + AsyncWrite, { fn handle(&mut self, msg: Result, _: &mut Context) { if let Ok(Frame::Text(txt)) = msg { println!("Server: {:?}", txt) } } fn started(&mut self, _ctx: &mut Context) { println!("Connected"); } fn finished(&mut self, ctx: &mut Context) { println!("Server disconnected"); ctx.stop() } } impl actix::io::WriteHandler for ChatClient where T: AsyncRead + AsyncWrite { }