CSE 542S: Studio 19

Asynchronous Programming


In today's studio you will explore Rust's asynchronous programming features, including futures, await expressions, and the block_on call that synchronous code can use to invoke asynchronous code and block until it completes.


Please complete the following required exercises. I encourage you to please work in groups of 2 or 3 people on each studio (and the groups are allowed to change from studio to studio) though if you would prefer to complete any studio by yourself that is also allowed.

As you work through these exercises, please record your answers, and when you finish them please log into Canvas, select this course in this semester, and then on the Canvas page for this studio assignment upload (1) a file containing your answers and (2) any code you produced while answering the exercises. Only one submission per team, please, and if you need to re-submit it the person who originally submitted the studio should please be the one to do that.

Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.


Required Exercises

  1. As the answer to the first exercise, list the names of the people who worked together on this studio.

  2. Log in using ssh into shell.cec.wustl.edu using your WUSTL Key id and password, issue the qlogin command to get onto one of the Linux Lab machines, and then within the directory you created for this course, add a new directory for this studio.

    In that new directory, use the cargo new command to create a new package (named e.g., rustasyncserver).

    Change into the src directory within that package and at the top of the main.rs file that it contains add the statement

    use async_std::net::TcpListener;

    Try to compile and run your program, and as the answer to this exercise please show the error that occurred.

  3. In the Cargo.toml file in the top level directory for the package, add the following line to the [dependencies] section:

    async-std = { version = "1.7", features = ["unstable"] }

    Compile and run your program, which will take a while since Rust will download and build all the necessary crates locally. As the answer to this exercise please show the output that the program produced when it ran.

  4. Modify the main function in the main.rs file so that it declares a future variable (e.g., named bind_future) that is initialized with a call to TcpListener::bind("127.0.0.1:7777") and then has a statement that uses an await expression on the variable (e.g., bind_future.await;).

    Try to compile and run your program, and as the answer to this exercise please show the error that occurred.

  5. Modify the main function so that instead of using an await expression on the variable, it (1) passes the future variable into a call to async_std::task::block_on, (2) matches on the result returned by async_std::task::block_on, and (3) prints out an appropriate message indicating whether binding the listener succeeded (Ok) or failed (Err).

    Compile and run your program, and as the answer to this exercise please show the output the program produced.

    As needed (e.g., if multiple groups qlogin to the same Linux Lab machine and all try to bind on port 7777, so some of those calls may fail) please feel free to vary which port number you use, as long as you use the same port number in your server code and the client code you will develop later in this studio.

  6. Above the main function, declare an async fn named run_server that takes no arguments and has a return type of std::io::Result<String>. In the body of the run_server function match on the result of the expression TcpListener::bind("127.0.0.1:7777").await; return the error if one occurred, or a String with a message indicating success otherwise.

    In the main function initialize the future variable with a call to run_server instead of a call to TcpListener::bind, and if the call to run_server succeeded print out the message from it.

    Compile and run your program, and as the answer to this question please show the output it produced.

  7. Modify your run_server function so that after binding successfully it (1) declares a connection establishment variable initialized with a call to the listener's incoming method and then (2) in a while let expression matches repeatedly on Some values containing a result produced by an await expression on a call to the connection establishment variable's next method, and for each successful one reads and prints out data from the socket carried by the Ok value. Note that this code is similar in structure to the example shown on page 542 of the BOT textbook, but is simpler in its functionality.

    Compile and run your program and confirm that it outputs a message saying it bound successfully, and then is waiting for connections. Use Ctrl-C to terminate the program, and as the answer to this exercise please show the code you wrote for the run_server function.

  8. In the top-level directory for this studio, use the cargo new command to create another new package (named e.g., rustasyncclient).

    Change into the src directory within that package and at the top of the main.rs file that it contains add the statement

    use async_std::net::TcpStream;

    Also add the line

    async-std = { version = "1.7", features = ["unstable"] }
    to the [dependencies] section of the rustasyncclient/Cargo.toml file.

    Modify the main function so that it matches on the result of a call to async_std::task::block_on(TcpStream::connect("127.0.0.1:7777")), prints out a message indicating whether the connection was successfully established, and if successful sends text over the established connection to the server

    Open another terminal window and in it ssh into the same Linux Lab machine where you will be running the client, and cd into the target/debug directory of the asynchronous server package, and use the compiled binary to run the server.

    Back in the original terminal window, compile and run the asynchronous client and as the answer to this exercise please show the output that both the client and server programs produced.

Things to Turn In:

For this studio, please turn in the following:


Page posted Monday November 11, 2024, by Chris Gill.