各位老师,我是一个rust新手尝试使用tokio做一些实验。目前碰到一个问题,我模拟了一个客户端client.rs,想要他和服务端server.rs进行通讯。客户端发送一些信息给到服务端,进行处理后再把结果发回来。
目前的代码会出现客户端卡死,用try_read看了一下原因是WouldBlock错误,单发送和单接收都正常。一旦像代码中出现发送后再接收就会出问题。能否有大佬解释一下原因,谢谢。
client.rs
use clap::{Parser, ValueEnum};
use serde::{Deserialize, Serialize};
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
net::{TcpSocket, TcpStream},
};
type BoxedError = Box<dyn std::error::Error>;
#[derive(Serialize, Deserialize)]
struct RequestFrame {
command: String,
key: String,
value: Option<String>,
}
impl RequestFrame {
fn new(command: String, key: String, value: Option<String>) -> RequestFrame {
RequestFrame {
command: command,
key: key,
value: value,
}
}
}
#[derive(Parser, Debug)]
#[command(
version = "0.0.1",
author = "haozhang",
long_about = "this is a self-made redis client"
)]
struct Args {
#[arg(short, long, value_name = "command")]
command: Command,
#[arg(short, long, value_name = "key")]
key: String,
#[arg(short, long, value_name = "value")]
value: Option<String>,
}
#[derive(Debug, Clone, ValueEnum)]
enum Command {
Get,
Set,
}
async fn get_stream() -> Result<TcpStream, BoxedError> {
let addr = "127.0.0.0:6379".parse().unwrap();
let socket = TcpSocket::new_v4().unwrap();
let stream = socket.connect(addr).await.unwrap();
Ok(stream)
}
#[tokio::main]
async fn main() -> Result<(), BoxedError> {
// let args = std::env::args().collect::<Vec<String>>();
let mut stream = get_stream().await?;
let (mut reader, mut writer) = stream.split();
let args = Args::parse();
let command = match args.command {
Command::Get => "get".to_string(),
Command::Set => "set".to_string(),
};
let key = args.key;
let value = args.value;
// println!("{:?}", command);
// println!("{:?}", key);
// println!("{:?}", value);
let request = RequestFrame::new(command, key, value);
let request_json_string = serde_json::to_string(&request)?;
writer.write_all(request_json_string.as_bytes()).await?;
writer.flush().await?;
let mut buf = String::new();
reader.read_to_string(&mut buf).await?;
// let mut buf = [0; 100];
// reader.try_read(&mut buf)?;
println!("{:?}", buf);
println!("done");
Ok(())
}
server.rs
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
net::TcpListener,
};
type BoxedError = Box<dyn std::error::Error>;
#[tokio::main]
async fn main() -> Result<(), BoxedError> {
let listener = TcpListener::bind("0.0.0.0:6379").await?;
println!("listening on {}", listener.local_addr()?.port());
loop {
let (socket, _) = listener.accept().await?;
tokio::spawn(async {
match process(socket).await {
Ok(()) => (),
Err(e) => eprintln!("process occurs an error: {e}")
};
});
}
}
async fn process(mut socket: tokio::net::TcpStream) -> Result<(), BoxedError> {
let (mut reader, mut writer) = socket.split();
let mut buf = String::new();
reader.read_to_string(&mut buf).await?;
writer.write_all("we got the command, thanks".as_bytes()).await?;
writer.flush().await?;
println!("content: {}", buf);
Ok(())
}
用错方法了,server中的read_to_string是通过EOF作为结束标志的,这个一般是操作文件的。
这里需要通过read方法手动拼接结果