mod common;
use rzmq::{socket::SocketEvent, Context, Msg, SocketType, ZmqError};
use std::time::Duration;
use tokio::time::sleep;
use crate::common::wait_for_event;
const REP_ADDR: &str = "tcp://127.0.0.1:5555";
const NUM_REQUESTS: usize = 500;
async fn run_rep_server(ctx: Context) -> Result<(), ZmqError> {
let rep_socket = ctx.socket(SocketType::Rep)?;
println!("[REP] Binding to {}...", REP_ADDR);
rep_socket.bind(REP_ADDR).await?;
println!("[REP] Bound and waiting for requests...");
for i in 0..NUM_REQUESTS {
let received_msg = rep_socket.recv().await?;
let request_str = String::from_utf8_lossy(received_msg.data().unwrap_or_default());
println!("[REP] Received request ({}): '{}'", i, request_str);
sleep(Duration::from_millis(100)).await;
let reply_str = format!("World_{}", i);
rep_socket.send(Msg::from_vec(reply_str.as_bytes().to_vec())).await?;
println!("[REP] Sent reply: '{}'", reply_str);
}
println!("[REP] Processed all requests. Closing socket.");
rep_socket.close().await?;
Ok(())
}
async fn run_req_client(ctx: Context) -> Result<(), ZmqError> {
let req_socket = ctx.socket(SocketType::Req)?;
println!("[REQ] Connecting to {}...", REP_ADDR);
let req_socket_monitor = req_socket.monitor_default().await?;
req_socket.connect(REP_ADDR).await?;
wait_for_event(&req_socket_monitor, Duration::from_secs(10), |event| matches!(event, SocketEvent::HandshakeSucceeded { .. })).await.map_err(|msg| ZmqError::Internal(msg.to_string()))?;
println!("[REQ] Connected.");
for i in 0..NUM_REQUESTS {
let request_str = format!("Hello_{}", i);
println!("[REQ] Sending request ({}): '{}'", i, request_str);
req_socket.send(Msg::from_vec(request_str.into_bytes())).await?;
let reply_msg = req_socket.recv().await?;
let reply_str = String::from_utf8_lossy(reply_msg.data().unwrap_or_default());
println!("[REQ] Received reply: '{}'", reply_str);
sleep(Duration::from_millis(500)).await; }
println!("[REQ] Sent all requests. Closing socket.");
req_socket.close().await?;
Ok(())
}
#[tokio::main]
async fn main() -> Result<(), ZmqError> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO) .init();
println!("--- Request-Reply Example ---");
let ctx = Context::new()?;
let server_ctx = ctx.clone();
let server_handle = tokio::spawn(async move {
if let Err(e) = run_rep_server(server_ctx).await {
eprintln!("[REP] Error: {}", e);
}
});
sleep(Duration::from_millis(200)).await;
let client_ctx = ctx.clone();
let client_handle_1 = tokio::spawn(async move {
if let Err(e) = run_req_client(client_ctx).await {
eprintln!("[REQ] Error: {}", e);
}
});
let client_ctx = ctx.clone();
let client_handle_2 = tokio::spawn(async move {
if let Err(e) = run_req_client(client_ctx).await {
eprintln!("[REQ] Error: {}", e);
}
});
let client_ctx = ctx.clone();
let client_handle_3 = tokio::spawn(async move {
if let Err(e) = run_req_client(client_ctx).await {
eprintln!("[REQ] Error: {}", e);
}
});
let _ = tokio::try_join!(server_handle, client_handle_1, client_handle_2, client_handle_3);
println!("[Main] Terminating context...");
ctx.term().await?;
println!("--- Request-Reply Example Finished ---");
Ok(())
}