Multithreading 多线程客户端,在一个队列中发送数据并在另一个队列中存储数据,同时不在Rust Tokio中阻塞
我很难制作一个Tokio客户端,它从服务器接收数据包并将它们存储在一个队列中供主线程处理,同时能够从另一个队列向服务器发送数据包 我试图做一个非常简单的在线游戏演示,有一个游戏客户端,它发送数据(它自己的修改状态,如玩家移动)并接收数据(其他玩家和服务器修改的游戏状态,如NPC/其他也移动的玩家) 这个想法是让一个网络线程访问存储序列化数据的两个Multithreading 多线程客户端,在一个队列中发送数据并在另一个队列中存储数据,同时不在Rust Tokio中阻塞,multithreading,asynchronous,rust,rust-tokio,Multithreading,Asynchronous,Rust,Rust Tokio,我很难制作一个Tokio客户端,它从服务器接收数据包并将它们存储在一个队列中供主线程处理,同时能够从另一个队列向服务器发送数据包 我试图做一个非常简单的在线游戏演示,有一个游戏客户端,它发送数据(它自己的修改状态,如玩家移动)并接收数据(其他玩家和服务器修改的游戏状态,如NPC/其他也移动的玩家) 这个想法是让一个网络线程访问存储序列化数据的两个arc持有mutex的Vec。一个弧用于入包,另一个用于出包IncomingPackets将由从服务器发送到客户端的数据包填充,这些数据包稍后将由主线程
arc
持有mutex
的Vec
。一个弧
用于入包
,另一个用于出包
IncomingPackets
将由从服务器发送到客户端的数据包填充,这些数据包稍后将由主线程读取,OutgoingPackets
将由主线程用应该发送到服务器的数据包填充
我似乎无法在其他线程中接收或发送数据包
客户机将只连接到服务器,服务器将允许许多客户机(这些客户机将单独提供服务)
关于stream的使用和实现的解释对新手来说并不友好,但我认为我应该以某种方式使用它们
我写了一些代码,但它不工作,可能是错误的
(我的原始代码未编译,因此请将其视为伪代码,抱歉)
extern板条箱字节顺序;//1.3.4
外部板条箱期货;//0.3.5
东京外部板条箱;//0.2.21
使用字节::字节;
使用期货:未来;
使用std::error::error;
使用std::sync::{Arc,Mutex};
使用tokio::net::TcpStream;
使用字节顺序::{BigEndian,writeByteXet};
使用std::io;
使用std::time::Duration;
使用tokio::io::AsyncReadExt;
使用tokio::io::AsyncWriteText;
使用tokio::net::tcp:{ReadHalf,WriteHalf};
//这是位于板条箱结构中的SharedPackets结构
结构共享数据包{
数据:互斥锁,
}
#[tokio::main]
异步fn main()->结果{
让mut stream=TcpStream::connect(“127.0.0.1:8080”)。等待?;
let(mut r,mut w)=stream.split();
让mut inc:Vec=Vec::new();
inc.push(字节::from(“Wow”);
让mut incoming_packets=Arc::new(SharedPackets{
数据:互斥:新(公司),
});
让mut out:Vec=Vec::new();
输出推送(字节::来自(“哇”);
让mut outgoint_packets=Arc::new(SharedPackets{
数据:互斥体::新建(outg),
});
让mut local_incoming_packets=Arc::clone(&incoming_packets);
让mut local_outgoint_packets=Arc::clone(&outgoint_packets);
让mut-rarc=Arc::new(Mutex::new(r));
让mut warc=Arc::new(Mutex::new(w));
东京:产卵(异步移动){
//发送和接收都是包含无限循环的异步函数
//它们基本上使用AsyncWriteText和AsyncReadExt来操作流的两部分
//send读取队列并将此数据写入套接字
//recv读取套接字并将此数据写入队列
//两个“队列”都由主线程操作
让mut read=&*rarc.lock().unwrap();
让mut write=&*warc.lock().unwrap();
未来::尝试加入(
发送(&mut write,&mut local_outgoint_数据包),
recv(&mut read,&mut local_传入_数据包),
)
等候
});
环路{
//在传入和传出数据包上读写其他内容
//直到节目结束
}
}
异步fn recv(读卡器:&mut ReadHalf,队列:&mut Arc)->结果{
环路{
//任务::睡眠(持续时间::从_millis(300))。等待;
{
设a=vec![“AAAA”];
国际热核聚变实验堆(iter)中的i{
让mut byte_array=vec![];
设str_bytes=i.as_bytes();
writeBytes语句::write_u32::(&mut byte_数组,str_bytes.len()作为u32)
.unwrap();
字节数组。扩展(str_字节);
writer.write(&byte_数组)。等待?;
}
}
}
}
这不会编译:
错误:无法在线程之间安全地发送future
-->src/main.rs:46:5
|
46 |东京::产卵(异步移动{
|^^^^^^^^^^^^^^^^异步块创建的未来不是“发送”`
|
:::/.cargo/registry/src/github.com-1ec6299db9ec823/tokio-0.2.21/src/task/spawn.rs:127:21
|
127 | T:未来+发送+静态,
|----此绑定在'tokio::spawn'中需要`
|
=帮助:在“impl futures::Future”中,“std::sync::MutexGuard”没有实现特征“std::marker::Send”`
注意:future不是'Send',因为此值在等待过程中使用
-->src/main.rs:55:9
|
52 |让mut读取=&*rarc.lock().unwrap();
|--------------具有类型'std::sync::MutexGuard>',而不是'Send'`
...
55 |/未来::尝试加入(
56 | |发送(&mut write,&mut local_outgoint_数据包),
57 | | recv(&mut read,&mut local|传入|U数据包),
58 | | )
59 | |等待;
||
60 | });
|-`rarc.lock().unwrap()`稍后会放在这里
帮助:考虑把它变成一个“让”绑定来创建一个较短的活期借款。
-->src/main.rs:52:25
|
52 |让mut读取=&*rarc.lock().unwrap();
| ^^^^^^^^^^^^^^^^^^^^^
错误:无法在线程之间安全地发送future
-->src/main.rs:46:5
|
46 |东京::产卵(异步移动{
|^^^^^^^^^^^^^^^^异步块创建的未来不是“发送”`
|
:::/.cargo/registry/src/github.com-1ec6299db9ec823/tokio-0.2.21/src/task/spawn.rs:127:21
|
127 | T:未来+发送+静态,
| --
extern crate byteorder; // 1.3.4
extern crate futures; // 0.3.5
extern crate tokio; // 0.2.21
use bytes::Bytes;
use futures::future;
use std::error::Error;
use std::sync::{Arc, Mutex};
use tokio::net::TcpStream;
use byteorder::{BigEndian, WriteBytesExt};
use std::io;
use std::time::Duration;
use tokio::io::AsyncReadExt;
use tokio::io::AsyncWriteExt;
use tokio::net::tcp::{ReadHalf, WriteHalf};
//This is the SharedPackets struct that is located in the crate structures
struct SharedPackets {
data: Mutex<Vec<bytes::Bytes>>,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut stream = TcpStream::connect("127.0.0.1:8080").await?;
let (mut r, mut w) = stream.split();
let mut inc: Vec<bytes::Bytes> = Vec::new();
inc.push(Bytes::from("Wow"));
let mut incoming_packets = Arc::new(SharedPackets {
data: Mutex::new(inc),
});
let mut outg: Vec<bytes::Bytes> = Vec::new();
outg.push(Bytes::from("Wow"));
let mut outgoint_packets = Arc::new(SharedPackets {
data: Mutex::new(outg),
});
let mut local_incoming_packets = Arc::clone(&incoming_packets);
let mut local_outgoint_packets = Arc::clone(&outgoint_packets);
let mut rarc = Arc::new(Mutex::new(r));
let mut warc = Arc::new(Mutex::new(w));
tokio::spawn(async move {
//send and receive are both async functions that contain an infinite loop
//they basically use AsyncWriteExt and AsyncReadExt to manipulate both halves of the stream
//send reads the queue and write this data on the socket
//recv reads the socket and write this data on the queue
//both "queues" are manipulated by the main thread
let mut read = &*rarc.lock().unwrap();
let mut write = &*warc.lock().unwrap();
future::try_join(
send(&mut write, &mut local_outgoint_packets),
recv(&mut read, &mut local_incoming_packets),
)
.await;
});
loop {
//read & write other stuff on both incoming_packets & outgoint_packets
//until the end of the program
}
}
async fn recv(reader: &mut ReadHalf<'_>, queue: &mut Arc<SharedPackets>) -> Result<(), io::Error> {
loop {
let mut buf: Vec<u8> = vec![0; 4096];
let n = match reader.read(&mut buf).await {
Ok(n) if n == 0 => return Ok(()),
Ok(n) => n,
Err(e) => {
eprintln!("failed to read from socket; err = {:?}", e);
return Err(e);
}
};
}
}
async fn send(writer: &mut WriteHalf<'_>, queue: &mut Arc<SharedPackets>) -> Result<(), io::Error> {
loop {
//task::sleep(Duration::from_millis(300)).await;
{
let a = vec!["AAAA"];
for i in a.iter() {
let mut byte_array = vec![];
let str_bytes = i.as_bytes();
WriteBytesExt::write_u32::<BigEndian>(&mut byte_array, str_bytes.len() as u32)
.unwrap();
byte_array.extend(str_bytes);
writer.write(&byte_array).await?;
}
}
}
}
extern crate futures; // 0.3.5; // 0.1.36std;
extern crate tokio; // 0.2.21;
extern crate byteorder; // 1.3.4;
use std::{error::Error};
use std::sync::{Arc};
use tokio::sync::Mutex;
use tokio::net::TcpStream;
use futures::{future};
use bytes::Bytes;
use std::io;
use std::time::Duration;
use tokio::io::AsyncWriteExt;
use tokio::io::AsyncReadExt;
use tokio::net::tcp::{ReadHalf, WriteHalf};
use byteorder::{BigEndian, WriteBytesExt};
//This is the SharedPackets struct that is located in the crate structures
struct SharedPackets {
data: Mutex<Vec<bytes::Bytes>>
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let mut inc : Vec<bytes::Bytes> = Vec::new();
inc.push(Bytes::from("Wow"));
let mut incoming_packets = Arc::new(SharedPackets {
data: Mutex::new(inc)
});
let mut outg : Vec<bytes::Bytes> = Vec::new();
outg.push(Bytes::from("Wow"));
let mut outgoint_packets = Arc::new(SharedPackets {
data: Mutex::new(outg)
});
let mut local_incoming_packets = Arc::clone(&incoming_packets);
let mut local_outgoint_packets = Arc::clone(&outgoint_packets);
tokio::spawn(async move {
let mut stream = TcpStream::connect("127.0.0.1:8080").await.unwrap();
let (mut r, mut w) = stream.split();
let mut rarc = Arc::new(Mutex::new(& mut r));
let mut warc = Arc::new(Mutex::new(& mut w));
//send and receive are both async functions that contain an infinite loop
//they basically use AsyncWriteExt and AsyncReadExt to manipulate both halves of the stream
//send reads the queue and write this data on the socket
//recv reads the socket and write this data on the queue
//both "queues" are manipulated by the main thread
//let mut read = &*rarc.lock().await;
//let mut write = &*warc.lock().await;
future::try_join(send(warc.clone(), &mut local_outgoint_packets), recv(rarc.clone(), &mut local_incoming_packets)).await;
});
loop {
//read & write other stuff on both incoming_packets & outgoint_packets
//until the end of the program
}
}
async fn recv(readerw: Arc<Mutex<&mut ReadHalf<'_>>>, queue: &mut Arc<SharedPackets>) -> Result<(), io::Error> {
let mut reader = readerw.lock().await;
loop {
let mut buf : Vec<u8> = vec![0; 4096];
let n = match reader.read(&mut buf).await {
Ok(n) if n == 0 => return Ok(()),
Ok(n) => n,
Err(e) => {
eprintln!("failed to read from socket; err = {:?}", e);
return Err(e);
}
};
}
}
async fn send(writerw: Arc<Mutex<&mut WriteHalf<'_>>>, queue: &mut Arc<SharedPackets>) -> Result<(), io::Error> {
let mut writer = writerw.lock().await;
loop{
//task::sleep(Duration::from_millis(300)).await;
{
let a = vec!["AAAA"];
for i in a.iter() {
let mut byte_array = vec![];
let str_bytes = i.as_bytes();
WriteBytesExt::write_u32::<BigEndian>(&mut byte_array, str_bytes.len() as u32).unwrap();
byte_array.extend(str_bytes);
writer.write(&byte_array).await?;
}
}
}
}