Synchronous communication between processes

I have a server that starts a client with

    let mut client = Command::new("./target/debug/client")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()?;

The problem is that it hangs after the first message. (I plan to use async, but I thought I'd start with something simple. Now I'm just puzzled.)

Here's what I get when I send a single message.

Server start with PID 85604
Server: run ./target/debug/client
Server sending to client PID 85625
Server reading from client
  Client Start
  Client 85625 read from server
  Client 85625 got 'Hello from Server' from server
  Client 85625 sending to server
  Client 85625 sleeping
  Client 85625 awake
  Client 85625 Exit
Server got from client 'Client 85625 got Hello from Server  '
Server sleeping
Server awake

I put the 5 second sleeps in to check for interleaving, which doesn't appear to be happening.

Here's what I get when I send two messages.

Server start with PID 85467
Server: run ./target/debug/client
Server sending to client PID 85482
Server sending to client PID 85482
Server reading from client
  Client Start
  Client 85482 read from server
  Client 85482 got 'Hello from Server ' from server
  Client 85482 sending to server
  Client 85482 read from server

I'm sure the problem is something simple that I'm just not seeing.

The relevant part of the server is

fn talk_to_client(pid: u32, msg: &[u8], to_client: &mut ChildStdin, from_client: &mut ChildStdout,) -> Result<(), std::io::Error> {
    println!("Server sending to client PID {}", pid);
    to_client.write_all(msg)?;
    let mut line = String::new();
    println!("Server reading from client");
    from_client.read_to_string(&mut line)?;
    println!("Server got from client '{}'",buf.to_string().replace("\n", " "));
    Ok(())
}

and the client

fn talk_to_server() -> Result<(), std::io::Error> {
    let client_pid = std::process::id();
    let mut to_server = stdout();
    let from_server = stdin();
    let mut line = String::new();
    eprintln!("  Client {} read from server", client_pid);
    from_server.read_line(&mut line)?;
    eprintln!("  Client {} got '{}' from server", client_pid, line.replace("\n", ""));
    eprintln!("  Client {} sending to server", client_pid);
    to_server.write_all(&format!("Client {} got {}\n", client_pid, line).as_bytes())?;
    Ok(())
}

The read_to_string method will not return until the writer closes the connection.

I suggest using a serialization format that knows its message size. Something simple like <length><data of that length> that lets you read_exact it. I use bincode for this.

Thanks, @alice and @kornel. I knew it had to be something simple.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.