Multithreading 多线程客户端,在一个队列中发送数据并在另一个队列中存储数据,同时不在Rust Tokio中阻塞

Multithreading 多线程客户端,在一个队列中发送数据并在另一个队列中存储数据,同时不在Rust Tokio中阻塞,multithreading,asynchronous,rust,rust-tokio,Multithreading,Asynchronous,Rust,Rust Tokio,我很难制作一个Tokio客户端,它从服务器接收数据包并将它们存储在一个队列中供主线程处理,同时能够从另一个队列向服务器发送数据包 我试图做一个非常简单的在线游戏演示,有一个游戏客户端,它发送数据(它自己的修改状态,如玩家移动)并接收数据(其他玩家和服务器修改的游戏状态,如NPC/其他也移动的玩家) 这个想法是让一个网络线程访问存储序列化数据的两个arc持有mutex的Vec。一个弧用于入包,另一个用于出包IncomingPackets将由从服务器发送到客户端的数据包填充,这些数据包稍后将由主线程

我很难制作一个Tokio客户端,它从服务器接收数据包并将它们存储在一个队列中供主线程处理,同时能够从另一个队列向服务器发送数据包

我试图做一个非常简单的在线游戏演示,有一个游戏客户端,它发送数据(它自己的修改状态,如玩家移动)并接收数据(其他玩家和服务器修改的游戏状态,如NPC/其他也移动的玩家)

这个想法是让一个网络线程访问存储序列化数据的两个
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?;
         }
     }
}
}