use*_*897 9 multithreading threadpool rust rust-cargo rust-tokio
我正在尝试用 Rust 制作一个多线程 tcp 通信程序
这个想法是主线程上存在一个侦听套接字,并且当连接进入时,工作由工作线程处理
我之前使用了 Rust 书中找到的 ThreadPool 方法,但据我了解,tokio 能够“自动”将工作分配给池中的线程
我对操作系统线程和 tokio 任务之间的区别感到困惑(主要是因为您用来spawn创建两者)
这是一些代码
fn main() {
println!("Hello World!");
let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(192, 168, 103, 7)), 2048);
println!("socket -> {}", socket);
// You need to use the tokio runtime to execute async functions
let rt = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(async {
let listener = StartListen::new(socket).await.unwrap();
});
}
Run Code Online (Sandbox Code Playgroud)
我StartListen在另一个文件中定义了
// Defines the StartListen class
pub struct StartListen {
listener: TcpListener,
}
// Implementation for StartListen class
impl StartListen {
pub async fn new(socket: SocketAddr) -> Result<StartListen, StartListenError>{
println!("Attempting to listen");
let bind_result = TcpListener::bind(socket).await;
sleep(Duration::from_secs(5)).await;
match bind_result {
Ok(listener) => {
println!("Server is listening on {}", &socket);
Ok(StartListen { listener })
}
Err(err) => Err(StartListenError::BindError(err)),
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了添加更多上下文,这个想法是这个套接字期望有两种类型的消息
// Defines the types of messages to expect
pub enum RequestType {
RequestWork {
request_message: String,
parameter: String,
sender_timestamp: String,
},
CloseConnection {
initial_timestamp: String,
final_timestamp: String,
},
Invalid(String),
}
Run Code Online (Sandbox Code Playgroud)
我还没有添加handle_connection方法,我是否必须定义handle_connection 才能坐在循环中并生成任务?
pub async fn accept_connections(&self) {
loop {
let (mut stream, addr) = self.listener.accept().await.unwrap();
println!("New connection from {}", addr);
// Spawn a new task to handle the connection
tokio::spawn(async move {
let mut buffer = [0; 1024];
loop {
let n = match stream.read(&mut buffer).await {
Ok(n) if n == 0 => return, // Connection closed
Ok(n) => n,
Err(e) => {
eprintln!("Error reading from socket: {}", e);
return;
}
};
// Convert the received message into a RequestType
let message = String::from_utf8_lossy(&buffer[..n]);
Run Code Online (Sandbox Code Playgroud)
Fin*_*nis 19
你已经非常接近理解了。你问的是正确的问题。
让我简要介绍一下可能的服务器实现:
tokio。如果你简单地这样做#[tokio::main],这就是你会得到的。不过,还有很多微妙之处需要考虑。我强烈建议阅读tokio 教程,它解释了其中的许多概念。之后,我建议阅读async 书籍。
例如,一些重要的微妙之处:
.await点处切换任务,因此每当您等待某件事时,请确保它在某个.await点内。(例外:短暂的std::sync::Mutex,请参见此处).await。相反,使用 将其卸载到真实线程spawn_blocking,这会.await向工作线程引入一个点并在不同的线程池上执行实际计算。| 归档时间: |
|
| 查看次数: |
4123 次 |
| 最近记录: |