mirror of
https://github.com/actix/examples
synced 2025-02-17 07:23:29 +01:00
Merge pull request #863 from c-git/add-client
Move client file from old echo example to actorless
This commit is contained in:
commit
4e35739c1c
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -8916,10 +8916,12 @@ dependencies = [
|
|||||||
"actix-files",
|
"actix-files",
|
||||||
"actix-web",
|
"actix-web",
|
||||||
"actix-ws",
|
"actix-ws",
|
||||||
|
"awc",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"log",
|
"log",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3,11 +3,21 @@ name = "websockets-echo-actorless-example"
|
|||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "websocket-server"
|
||||||
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "websocket-client"
|
||||||
|
path = "src/client.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-files.workspace = true
|
actix-files.workspace = true
|
||||||
actix-web.workspace = true
|
actix-web.workspace = true
|
||||||
actix-ws.workspace = true
|
actix-ws.workspace = true
|
||||||
|
awc.workspace = true
|
||||||
env_logger.workspace = true
|
env_logger.workspace = true
|
||||||
futures-util.workspace = true
|
futures-util = { workspace = true, features = ["sink"] }
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
tokio = { workspace = true, features = ["rt", "time", "macros"] }
|
tokio = { workspace = true, features = ["rt", "time", "macros"] }
|
||||||
|
tokio-stream.workspace = true
|
||||||
|
@ -8,7 +8,7 @@ Simple echo websocket server using [`actix-ws`].
|
|||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd websockets/echo-actorless
|
cd websockets/echo-actorless
|
||||||
cargo run
|
cargo run --bin websocket-server
|
||||||
# starting HTTP server at http://localhost:8080
|
# starting HTTP server at http://localhost:8080
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -16,6 +16,13 @@ cargo run
|
|||||||
|
|
||||||
Go to <http://localhost:8080> in a browser.
|
Go to <http://localhost:8080> in a browser.
|
||||||
|
|
||||||
|
### rust client
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd websockets/echo-actorless
|
||||||
|
cargo run --bin websocket-client
|
||||||
|
```
|
||||||
|
|
||||||
### CLI Client
|
### CLI Client
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
|
72
websockets/echo-actorless/src/client.rs
Normal file
72
websockets/echo-actorless/src/client.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
//! Simple websocket client.
|
||||||
|
|
||||||
|
use std::{io, thread};
|
||||||
|
|
||||||
|
use actix_web::web::Bytes;
|
||||||
|
use awc::ws;
|
||||||
|
use futures_util::{SinkExt as _, StreamExt as _};
|
||||||
|
use tokio::{select, sync::mpsc};
|
||||||
|
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() {
|
||||||
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||||
|
|
||||||
|
log::info!("starting echo WebSocket client");
|
||||||
|
|
||||||
|
let (cmd_tx, cmd_rx) = mpsc::unbounded_channel();
|
||||||
|
let mut cmd_rx = UnboundedReceiverStream::new(cmd_rx);
|
||||||
|
|
||||||
|
// run blocking terminal input reader on separate thread
|
||||||
|
let input_thread = thread::spawn(move || loop {
|
||||||
|
let mut cmd = String::with_capacity(32);
|
||||||
|
|
||||||
|
if io::stdin().read_line(&mut cmd).is_err() {
|
||||||
|
log::error!("error reading line");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd_tx.send(cmd).unwrap();
|
||||||
|
});
|
||||||
|
|
||||||
|
let (res, mut ws) = awc::Client::new()
|
||||||
|
.ws("ws://127.0.0.1:8080/ws")
|
||||||
|
.connect()
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
log::debug!("response: {res:?}");
|
||||||
|
log::info!("connected; server will echo messages sent");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
select! {
|
||||||
|
Some(msg) = ws.next() => {
|
||||||
|
match msg {
|
||||||
|
Ok(ws::Frame::Text(txt)) => {
|
||||||
|
// log echoed messages from server
|
||||||
|
log::info!("Server: {txt:?}")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(ws::Frame::Ping(_)) => {
|
||||||
|
// respond to ping probes
|
||||||
|
ws.send(ws::Message::Pong(Bytes::new())).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(cmd) = cmd_rx.next() => {
|
||||||
|
if cmd.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.send(ws::Message::Text(cmd.into())).await.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
else => break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input_thread.join().unwrap();
|
||||||
|
}
|
@ -22,4 +22,4 @@ env_logger.workspace = true
|
|||||||
futures-util = { workspace = true, features = ["sink"] }
|
futures-util = { workspace = true, features = ["sink"] }
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { workspace = true, features = ["full"] }
|
||||||
tokio-stream = "0.1.8"
|
tokio-stream.workspace = true
|
||||||
|
@ -1,72 +0,0 @@
|
|||||||
//! Simple websocket client.
|
|
||||||
|
|
||||||
use std::{io, thread};
|
|
||||||
|
|
||||||
use actix_web::web::Bytes;
|
|
||||||
use awc::ws;
|
|
||||||
use futures_util::{SinkExt as _, StreamExt as _};
|
|
||||||
use tokio::{select, sync::mpsc};
|
|
||||||
use tokio_stream::wrappers::UnboundedReceiverStream;
|
|
||||||
|
|
||||||
#[actix_web::main]
|
|
||||||
async fn main() {
|
|
||||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
|
||||||
|
|
||||||
log::info!("starting echo WebSocket client");
|
|
||||||
|
|
||||||
let (cmd_tx, cmd_rx) = mpsc::unbounded_channel();
|
|
||||||
let mut cmd_rx = UnboundedReceiverStream::new(cmd_rx);
|
|
||||||
|
|
||||||
// run blocking terminal input reader on separate thread
|
|
||||||
let input_thread = thread::spawn(move || loop {
|
|
||||||
let mut cmd = String::with_capacity(32);
|
|
||||||
|
|
||||||
if io::stdin().read_line(&mut cmd).is_err() {
|
|
||||||
log::error!("error reading line");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd_tx.send(cmd).unwrap();
|
|
||||||
});
|
|
||||||
|
|
||||||
let (res, mut ws) = awc::Client::new()
|
|
||||||
.ws("ws://127.0.0.1:8080/ws")
|
|
||||||
.connect()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
log::debug!("response: {res:?}");
|
|
||||||
log::info!("connected; server will echo messages sent");
|
|
||||||
|
|
||||||
loop {
|
|
||||||
select! {
|
|
||||||
Some(msg) = ws.next() => {
|
|
||||||
match msg {
|
|
||||||
Ok(ws::Frame::Text(txt)) => {
|
|
||||||
// log echoed messages from server
|
|
||||||
log::info!("Server: {txt:?}")
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ws::Frame::Ping(_)) => {
|
|
||||||
// respond to ping probes
|
|
||||||
ws.send(ws::Message::Pong(Bytes::new())).await.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(cmd) = cmd_rx.next() => {
|
|
||||||
if cmd.is_empty() {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ws.send(ws::Message::Text(cmd.into())).await.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
else => break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
input_thread.join().unwrap();
|
|
||||||
}
|
|
1
websockets/echo/src/client.rs
Symbolic link
1
websockets/echo/src/client.rs
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../echo-actorless/src/client.rs
|
Loading…
x
Reference in New Issue
Block a user