Accepting sockets
The first thing our Redis server needs to do is to accept inbound TCP sockets. This is done with tokio::net::TcpListener.
Many of Tokio’s types are named the same as their synchronous equivalent in the Rust standard library. When it makes sense, Tokio exposes the same APIs as
stdbut usingasync fn.
A TcpListener is bound to port 6379, then sockets are accepted in a loop. Each socket is processed then closed. For now, we will read the command, print it to stdout and respond with an error.
1. use tokio::net::{TcpListener, TcpStream};
2. use mini_redis::{Connection, Frame};
4. #[tokio::main]
5. async fn main() {
6. // Bind the listener to the address
7. let listener = TcpListener::bind("127.0.0.1:6379").await.unwrap();
9. loop {
10. // The second item contains the IP and port of the new connection.
11. let (socket, _) = listener.accept().await.unwrap();
12. process(socket).await;
13. }
14. }
16. async fn process(socket: TcpStream) {
17. // The `Connection` lets us read/write redis **frames** instead of
18. // byte streams. The `Connection` type is defined by mini-redis.
19. let mut connection = Connection::new(socket);
21. if let Some(frame) = connection.read_frame().await.unwrap() {
22. println!("GOT: {:?}", frame);
24. // Respond with an error
25. let response = Frame::Error("unimplemented".to_string());
26. connection.write_frame(&response).await.unwrap();
27. }
28. }
Now, run this accept loop:
1. $ cargo run
In a separate terminal window, run the hello-redis example (the SET/GET command from the previous section):
1. $ cargo run --example hello-redis
The output should be:
1. Error: "unimplemented"
In the server terminal, the output is:
1. GOT: Array([Bulk(b"set"), Bulk(b"hello"), Bulk(b"world")])
