0

我已经实现了一个聊天服务器,它存储连接的用户,如果用户发送消息,服务器会将其回显给所有其他客户端。

我有 C++ 背景,所以我创建了一个全局static mut USERS:Vec<TcpStream>变量来存储和访问用户。

我正在处理来自 main() 的连接用户,如下所示:

#[async_std::main]
async fn main() -> io::Result<()>{
    let listener = TcpListener::bind("127.0.0.1:14530").await?;

    loop {
        let (stream, addr) = listener.accept().await?;
        
        unsafe {
            USERS.push(stream.clone());
        }
        
        task::spawn(on_connection(stream, addr));
    }
}

功能on_connection是:

async fn on_connection(mut stream:TcpStream, addr:SocketAddr) -> io::Result<()> {
    println!("New Connection: {}", addr.to_string());

    let mut buffer = [0u8; 1024];
    loop {
        let len = stream.read(&mut buffer).await?; 

        if len > 0 {
            print!("Message from {} => {}", addr.to_string(), String::from_utf8_lossy(&buffer));
            
            unsafe {
                for mut user in USERS.clone() {
                    user.write(&buffer).await?;
                }
            }
        }
        else {
            println!("Disconnected: {}", addr.to_string());
            
            break
        }
    };

    Ok(())
}

像这样使用 Rust 可以吗?

我想让应用程序安全并使用 Rust 的安全环境而没有“不安全”。但是我不知道如何存储全局用户以供以后访问而不会不安全。

4

1 回答 1

0

考虑到评论,这是我上面实现的“安全版本”:

use std::net::SocketAddr;
use async_std::net::{TcpStream, TcpListener};
use async_std::sync::{Arc, Mutex};
use async_std::io::{ReadExt, WriteExt, Result};
use async_std::task;


async fn on_connection(mut stream:TcpStream, addr:SocketAddr, users:Arc<Mutex<Vec<TcpStream>>>) -> Result<()> {
    println!("New Connection: {}", addr.to_string());

    let mut buffer = [0u8; 1024];
    loop {
        let len = stream.read(&mut buffer).await?; 

        if len > 0 {
            print!("{} => {}", addr.to_string(), String::from_utf8_lossy(&buffer));

            let users = users.lock().await;
            
            for mut user in &*users {
                // send everyone except itself
                if user.peer_addr()? != stream.peer_addr()? {
                    user.write(&buffer).await?;
                }
            }
        }
        else {
            println!("Disconnected: {}", addr.to_string());
            break;
        }
    };

    Ok(())
}

#[async_std::main]
async fn main() -> Result<()>{
    let listener = TcpListener::bind("127.0.0.1:14530").await?;
    let users = Vec::new();
    let arc_users = Arc::new(Mutex::new(users));
    
    loop {
        let users = arc_users.clone();
        let (stream, addr) = listener.accept().await?;

        let mut write_permission= users.lock().await;
        write_permission.push(stream.clone());
        drop(write_permission);
        
        task::spawn(on_connection(stream, addr, users));
    };
}

于 2021-11-24T14:31:52.770 回答