TCP socket doesn't read incoming data

I trying to send bidirectional messages using TCP sockets in Rust.
However, the messages don't get sent unless I stop the client process.

What am I missing?

Here, the server prints "I am client" if I stop the client program. I thought it might be due to buffering, so I tried clearing the flush but that didn't work.
Any suggestions?

server.rs

use std::io::{Read, Write};
use std::net::TcpListener;

fn main() {
    let listener = TcpListener::bind("127.0.0.1:7000").expect("Failed to bind a socket.");

    match listener.accept() {
        Ok((mut tcp_socket, _socket_addr)) => {
            let mut msg = String::new();
            tcp_socket
                .read_to_string(&mut msg)
                .expect("Failed to read.");
            // tcp_socket.flush().ok();

            println!("{}", msg);

            tcp_socket
                .write_fmt(format_args!("I am server.\n"))
                .expect("Failed to write.");
            // std::io::stdout().flush().ok();
            // tcp_socket.flush().ok();
        }
        Err(err) => println!("couldn't get client: {:?}", err),
    }
}

client.rs

use std::io::{Read, Write};
use std::net::TcpStream;

fn main() {
    let mut stream = TcpStream::connect("127.0.0.1:7000").expect("Failed to connect to server.");

    stream
        .write_fmt(format_args!("I am client.\n"))
        .expect("Failed to write.");
    // std::io::stdout().flush().ok();
    // stream.flush().ok();

    let mut msg = String::new();
    stream.read_to_string(&mut msg).expect("Failed to read.");
    // stream.flush().ok();

    println!("{}", msg);
}

I am able to so in C though.

server.c
#define _POSIX_C_SOURCE 200809L

#include <arpa/inet.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define MYPORT  "6001"
#define BACKLOG 10

int main(void) {
    int           sockfd, receiver_sockfd, status;
    const char*   sendd = "I am server.\n";
    unsigned char file_recv[100];

    struct addrinfo hints = {
        .ai_family   = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *servinfo, *it;

    if ((status = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        exit(EXIT_FAILURE);
    }

    for (it = servinfo; it != NULL; it = it->ai_next) {
        if ((sockfd = socket(it->ai_family, it->ai_socktype, it->ai_protocol)) == -1) {
            perror("socket");
            continue;
        }
        break;
    }

    if (bind(sockfd, it->ai_addr, it->ai_addrlen) == -1) {
        perror("bind");
        exit(EXIT_FAILURE);
    }

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(EXIT_FAILURE);
    }

    receiver_sockfd = accept(sockfd, it->ai_addr, &(it->ai_addrlen));
    if (receiver_sockfd == -1) {
        perror("accept");
        exit(EXIT_FAILURE);
    }

    if (recv(receiver_sockfd, file_recv, 100, 0) == -1) {
        perror("recv");
        exit(EXIT_FAILURE);
    }
    printf("%s", file_recv);

    if (write(receiver_sockfd, sendd, strlen(sendd)) == -1) {
        perror("write");
        exit(EXIT_FAILURE);
    }

    if (recv(receiver_sockfd, file_recv, 100, 0) == -1) {
        perror("recv");
        exit(EXIT_FAILURE);
    }
    printf("%s", file_recv);
    close(sockfd);
}
client.c
#define _POSIX_C_SOURCE 200809L

#include <arpa/inet.h>
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#define MYPORT    "6001"
#define BACKLOG   10
#define MAX_BYTES 1000000

int main(void) {
    int     sockfd, status;
    ssize_t bytes_received;

    unsigned char buf[MAX_BYTES];
    const char*   file_name = "I am client.\n";

    struct addrinfo hints = {
        .ai_family   = AF_INET,
        .ai_socktype = SOCK_STREAM,
    };
    struct addrinfo *servinfo, *it;

    if ((status = getaddrinfo(NULL, MYPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
        exit(EXIT_FAILURE);
    }

    for (it = servinfo; it != NULL; it = it->ai_next) {
        if ((sockfd = socket(it->ai_family, it->ai_socktype, it->ai_protocol)) == -1) {
            perror("socket");
            continue;
        }
        break;
    }

    if (connect(sockfd, it->ai_addr, it->ai_addrlen) == -1) {
        perror("connect");
        exit(EXIT_FAILURE);
    }

    if (write(sockfd, file_name, strlen(file_name)) == -1) {
        perror("write");
        exit(EXIT_FAILURE);
    }

    bytes_received = recv(sockfd, buf, MAX_BYTES, 0);
    printf("%s", buf);
    if (bytes_received == -1) {
        perror("recv");
        exit(EXIT_FAILURE);
    }

    if (write(sockfd, file_name, strlen(file_name)) == -1) {
        perror("write");
        exit(EXIT_FAILURE);
    }
}
The server prints `I am client.` and the client prints `I am server.`

The read_to_string method will continue reading until end-of-stream, so it blocks until the connection is closed. (This is why the server process does nothing until you kill the client.)

If you want your program to behave like the C version, replace the read_to_string with a single read call. Or you can call read in a loop until you see some delimeter character, like a newline.

Gotcha. Thanks for the quick reply!