Skip to content

TcpListener echo example is confusing #468

@95th

Description

@95th

Echo server example in TcpListener seems confusing to a new-comer.

while let Some(stream) = incoming.next().await {
    let stream = stream?;          -- Immutable binding
    let (reader, writer) = &mut (&stream, &stream);  -- This take mutable reference of immutable references
    io::copy(reader, writer).await?; -- but io requires mutable access.
}

It's not clear how io::copy can use reader and writer which are basically &mut &TcpStream

Activity

ghost

ghost commented on Nov 7, 2019

@ghost

This change would solve the problem: #365

Then one could write:

while let Some(stream) = incoming.next().await {
    let stream = stream?;
    io::copy(&stream, &stream).await?;
}
gyscos

gyscos commented on Jan 16, 2020

@gyscos

It can currently be written:

while let Some(stream) = incoming.next().await {
    let stream = stream?;
    io::copy(&mut &stream, &mut &stream).await?;
}

This is because we have something like impl Read for &TcpStream (and same thing for Write), so &stream is both Read and a Write. io::copy wants mutable reference to both, so &mut &stream is now a &mut impl Read.

I think another confusing part is how this example only processes one client at a time, which is a bit sad for an async framework. As is, if a client connects and keep the connection open, no other client can connect.

Spawning a task would be a better idea:

use async_std::{io, task};
use async_std::net::TcpListener;
use async_std::prelude::*;

#[async_std::main]
async fn main() -> io::Result<()> {
    let listener = TcpListener::bind("127.0.0.1:8080").await?;
    let mut incoming = listener.incoming();

    while let Some(stream) = incoming.next().await {
        let stream = stream?; // Implement both Read and Write

       task::spawn(async move {
            let (reader, writer) = &mut (&stream, &stream);
            io::copy(reader, writer).await.unwrap();
        });
    }

    Ok(())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @gyscos@yoshuawuyts@95th

        Issue actions

          TcpListener echo example is confusing · Issue #468 · async-rs/async-std