use std::io; #[cfg(windows)] async fn windows_main() -> io::Result<()> { use tokio::io::AsyncWriteExt; use tokio::io::{AsyncBufReadExt, BufReader}; use tokio::net::windows::named_pipe::{ClientOptions, ServerOptions}; const PIPE_NAME: &str = r"\\.\pipe\named-pipe-single-client"; let server = ServerOptions::new().create(PIPE_NAME)?; let server = tokio::spawn(async move { // Note: we wait for a client to connect. server.connect().await?; let mut server = BufReader::new(server); let mut buf = String::new(); server.read_line(&mut buf).await?; server.write_all(b"pong\n").await?; Ok::<_, io::Error>(buf) }); let client = tokio::spawn(async move { // There's no need to use a connect loop here, since we know that the // server is already up - `open` was called before spawning any of the // tasks. let client = ClientOptions::new().open(PIPE_NAME)?; let mut client = BufReader::new(client); let mut buf = String::new(); client.write_all(b"ping\n").await?; client.read_line(&mut buf).await?; Ok::<_, io::Error>(buf) }); let (server, client) = tokio::try_join!(server, client)?; assert_eq!(server?, "ping\n"); assert_eq!(client?, "pong\n"); Ok(()) } #[tokio::main] async fn main() -> io::Result<()> { #[cfg(windows)] { windows_main().await?; } #[cfg(not(windows))] { println!("Named pipes are only supported on Windows!"); } Ok(()) }