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.
As the answer to the first exercise, list the names of the people who worked together on this studio.
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.
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.
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.
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.
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.
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.
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.
For this studio, please turn in the following:
Page posted Monday November 11, 2024, by Chris Gill.