Rust Websocket客户端消息有效负载“;“活得不够长”;

Rust Websocket客户端消息有效负载“;“活得不够长”;,rust,Rust,我修改了以保存来自websocket服务器的消息负载: fn main() { let mut globaltest = ""; // ...some othercode let receive_loop = thread::spawn(move || { // Receive loop for message in receiver.incoming_messages() { let message: Mes

我修改了以保存来自websocket服务器的消息负载:

fn main()
{
    let mut globaltest = "";

    // ...some othercode


    let receive_loop = thread::spawn(move || {
        // Receive loop
        for message in receiver.incoming_messages() {
            let message: Message = match message {
                Ok(m) => m,
                Err(e) => {
                    println!("Receive Loop: {:?}", e);
                    let _ = tx_1.send(Message::close());
                    return;
                }
            };
            match message.opcode {
                Type::Close => {
                    // Got a close message, so send a close message and return
                    let _ = tx_1.send(Message::close());
                    return;
                }
                Type::Ping => match tx_1.send(Message::pong(message.payload)) {
                    // Send a pong in response
                    Ok(()) => (),
                    Err(e) => {
                        println!("Receive Loop: {:?}", e);
                        return;
                    }
                },
                // Say what we received
                _ => {
                    println!("Receive Loop: {:?}", message);
                        // recive from motion
                        let buf = &message.payload;
                        {
                            let s = match str::from_utf8(buf) {
                                Ok(v) => v,
                                Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
                            };
                            println!("{}",s);

                            ////>>> problem here <<<
                            globaltest = s;
                        }

                    },
            }
        }
    });


    // ...some othercode

}
我不知道为什么。我尝试了很多解决方案,如
Arc
Mutex
,但都不起作用:(

当我删除
globaltest=s
时,代码构建和运行都没有问题。因此我尝试编写一个更简单的示例:

use std::str;
use std::thread;

fn main() {

    let mut y = 2;

    let receive_loop = thread::spawn(move || {
         let x = 1;

         y = x;
          println!("tt{:?}",y);
    });

    let receive_loop2 = thread::spawn(move || {

          println!("tt2{:?}",y);
    });

  println!("{:?}",y);

}
这是一个几乎相同的结构

以下是完整代码,与rust websocket客户端示例略有不同:

extern crate websocket;

fn main() {
    use std::thread;
    use std::sync::mpsc::channel;
    use std::io::stdin;
    use std::str;
    use websocket::{Message, Sender, Receiver};
    use websocket::message::Type;
    use websocket::client::request::Url;
    use websocket::Client;

    let mut globaltest ="";

    let url = Url::parse("ws://127.0.0.1:2794").unwrap();

    println!("Connecting to {}", url);

    let request = Client::connect(url).unwrap();

    let response = request.send().unwrap(); // Send the request and retrieve a response

    println!("Validating response...");

    response.validate().unwrap(); // Validate the response

    println!("Successfully connected");

    let (mut sender, mut receiver) = response.begin().split();

    let (tx, rx) = channel();

    let tx_1 = tx.clone();

    let send_loop = thread::spawn(move || {
        loop {
            // Send loop
            let message: Message = match rx.recv() {
                Ok(m) => m,
                Err(e) => {
                    println!("Send Loop: {:?}", e);
                    return;
                }
            };
            match message.opcode {
                Type::Close => {
                    let _ = sender.send_message(&message);
                    // If it's a close message, just send it and then return.
                    return;
                },
                _ => (),
            }
            // Send the message
            match sender.send_message(&message) {
                Ok(()) => (),
                Err(e) => {
                    println!("Send Loop: {:?}", e);
                    let _ = sender.send_message(&Message::close());
                    return;
                }
            }
        }
    });

    let receive_loop = thread::spawn(move || {
        // Receive loop
        for message in receiver.incoming_messages() {
            let message: Message = match message {
                Ok(m) => m,
                Err(e) => {
                    println!("Receive Loop: {:?}", e);
                    let _ = tx_1.send(Message::close());
                    return;
                }
            };
            match message.opcode {
                Type::Close => {
                    // Got a close message, so send a close message and return
                    let _ = tx_1.send(Message::close());
                    return;
                }
                Type::Ping => match tx_1.send(Message::pong(message.payload)) {
                    // Send a pong in response
                    Ok(()) => (),
                    Err(e) => {
                        println!("Receive Loop: {:?}", e);
                        return;
                    }
                },
                // Say what we received
                _ => {
                    println!("Receive Loop: {:?}", message);
                        // recive from motion
                        let buf = &message.payload;
                        {
                            let s = match str::from_utf8(buf) {
                                Ok(v) => v,
                                Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
                            };
                            println!("{}",s);
                            globaltest = s;
                        }

                    },
            }
        }
    });

    loop {
        let mut input = String::new();

        stdin().read_line(&mut input).unwrap();

        let trimmed = input.trim();

        let message = match trimmed {
            "/close" => {
                // Close the connection
                let _ = tx.send(Message::close());
                break;
            }
            // Send a ping
            "/ping" => Message::ping(b"PING".to_vec()),
            // Otherwise, just send text
            _ => Message::text(trimmed.to_string()),
        };

        match tx.send(message) {
            Ok(()) => (),
            Err(e) => {
                println!("Main Loop: {:?}", e);
                break;
            }
        }
    }

    // We're exiting

    println!("Waiting for child threads to exit");

    let _ = send_loop.join();
    let _ = receive_loop.join();

    println!("Exited");
}

@fjh感谢您的回复

我将代码修改成这样,在
receive\u loop
中更改
globaltest
,并从主线程循环访问它。我仍然得到一个令人困惑的错误,即使花了三个小时,我仍然无法解决它:(

fn main(){
让mut globaltest:Arc=Arc::new(Mutex::new(String::from(“”));
//其他一些代码。。。
让receive_loop=thread::spawn(移动| |){
//接收环路
用于接收器中的消息。传入的_消息(){
让消息:消息=匹配消息{
Ok(m)=>m,
错误(e)=>{
println!(“接收循环:{:?}”,e);
让u=tx_1.send(Message::close());
返回;
}
};
匹配message.opcode{
类型::关闭=>{
//收到关闭消息,请发送关闭消息并返回
让u=tx_1.send(Message::close());
返回;
}
类型::Ping=>match tx_1.send(Message::pong(Message.payload)){
//发一个乒乓球作为回应
好(())=>(),
错误(e)=>{
println!(“接收循环:{:?}”,e);
返回;
}
},
//说说我们收到了什么
_ => { 
让mut globaltest_child=globaltest.lock().unwrap();
println!(“接收循环:{:?}”,消息);
//动静
让buf=&message.payload;
{
让s=match str::from_utf8(buf){
Ok(v)=>v,
Err(e)=>panic!(“无效的UTF-8序列:{}”,e),
};
{
//>>>如果我这样做,globaltest值将与globaltest_child相同??
*globaltest_child=String::from(s);
println!(“{:?}”,globaltest_child.clone());
}
} 
},
}
}
});
循环{
让消息=消息::文本(“mtconnect”);
匹配发送(消息){
好(())=>(),
错误(e)=>{
println!(“主循环:{:?}”,e);
打破
}
}
///>>>这里有问题////
println!(“{:?}”,globaltest.clone());
线程::睡眠(时间::持续时间::from_millis(3000));
} 
}
编译器总是告诉我:

athaniel@nathaniel-virtual-machine:~/rustcoderep/rsadapter$ sudo cargo run
   Compiling rsadapter v0.1.0 (file:///home/nathaniel/rustcoderep/rsadapter)
src/main.rs:166:25: 166:35 error: use of moved value: `globaltest` [E0382]
src/main.rs:166         println!("{:?}",globaltest.clone()); 
                                        ^~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:166:9: 166:45 note: in this expansion of println! (defined in <std macros>)
src/main.rs:166:25: 166:35 help: run `rustc --explain E0382` to see a detailed explanation
src/main.rs:102:35: 153:3 note: `globaltest` moved into closure environment here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<collections::string::String>>`, which is non-copyable
src/main.rs:102     let receive_loop = thread::spawn(move || {
src/main.rs:103         
src/main.rs:104       
src/main.rs:105         // Receive loop
src/main.rs:106         for message in receiver.incoming_messages() {
src/main.rs:107             let message: Message = match message {
                ...
src/main.rs:102:35: 153:3 help: perhaps you meant to use `clone()`?
error: aborting due to previous error
athaniel@nathaniel-虚拟机:~/rustcoderep/rsadapter$sudo货物运行
编译rsadapter v0.1.0(file:///home/nathaniel/rustcoderep/rsadapter)
src/main.rs:166:25:166:35错误:使用移动值:`globaltest`[E0382]
src/main.rs:166 println!(“{:?}”,globaltest.clone());
^~~~~~~~~~
:2:25:2:56注意:在格式的扩展中\u args!
:3:1:3:54注:在此打印扩展中!(在中定义)
src/main.rs:166:9:166:45注:在println!(在中定义)的扩展中
src/main.rs:166:25:166:35帮助:运行'rustc--explain E0382'查看详细说明
src/main.rs:102:35:153:3注意:`globaltest`移到了闭包环境中,因为它的类型为`alloc::arc::arc`,这是不可复制的
src/main.rs:102 let receive_loop=thread::spawn(move | |){
src/main.rs:103
src/main.rs:104
src/main.rs:105//接收循环
src/main.rs:106用于receiver.incoming_messages()中的消息{
src/main.rs:107让消息:消息=匹配消息{
...
src/main.rs:102:35:153:3帮助:也许你想使用“clone()”?
错误:由于上一个错误而中止
我仍然无法在另一个线程中访问
globaltest

当我删除
globaltest=s
时,代码构建和运行都没有问题

是的,因为该赋值不安全。您正试图从其他线程中修改主线程中声明的局部变量。这可能会导致各种问题,如数据争用,这就是为什么编译器不允许您这样做


如果你不知道你想做什么,就很难说什么是解决这个问题的最佳方法。也就是说,你可以通过将
globaltest
设置为
Arc
,而不是
&str
,来解决这个问题,这样你就可以从两个线程安全地访问它。

每当你遇到问题时,你应该花时间减少这有助于您了解问题所在,并可能删除可能使您困惑的无关细节

在这种情况下,您可以从删除所有其他
match
臂开始,用
panic!
调用替换它们。然后尝试用您自己的代码替换库,最后只使用标准库代码。最终,您将得到一些更小的方法来重现问题

这就是所谓的,当你问一个关于堆栈溢出的问题时,这是非常受鼓励的。但是,当你有一个你还不了解的问题时,它对你自己是100%有用的。作为一个专业程序员,你应该做这项工作

这里有一个可能的MCVE,我能创造出来
fn main() {

    let mut globaltest:Arc<Mutex<String>> = Arc::new(Mutex::new(String::from("")));

    //some other code...

    let receive_loop = thread::spawn(move || {

        // Receive loop
        for message in receiver.incoming_messages() {
            let message: Message = match message {
                Ok(m) => m,
                Err(e) => {
                    println!("Receive Loop: {:?}", e);
                    let _ = tx_1.send(Message::close());
                    return;
                }
            };
            match message.opcode {
                Type::Close => {
                    // Got a close message, so send a close message and return
                    let _ = tx_1.send(Message::close());
                    return;
                }
                Type::Ping => match tx_1.send(Message::pong(message.payload)) {
                    // Send a pong in response
                    Ok(()) => (),
                    Err(e) => {
                        println!("Receive Loop: {:?}", e);
                        return;
                    }
                },
                // Say what we received
                _ => { 
                        let mut globaltest_child = globaltest.lock().unwrap();

                        println!("Receive Loop: {:?}", message);
                        // recive from motion
                        let buf = &message.payload;
                        {
                            let s = match str::from_utf8(buf) {
                                Ok(v) => v,
                                Err(e) => panic!("Invalid UTF-8 sequence: {}", e),
                            };

                            {
                                //>>> if I do like this, globaltest value will same like globaltest_child??
                                *globaltest_child = String::from(s); 
                                println!("{:?}",globaltest_child.clone()); 
                            }
                        } 
                    },
            }
        }
    });

    loop { 
        let message = Message::text("mtconnect");

        match tx.send(message) {
            Ok(()) => (),
            Err(e) => {
                println!("Main Loop: {:?}", e);
                break;
            }
        }

        ///>>> problem here////
        println!("{:?}",globaltest.clone()); 
        thread::sleep(time::Duration::from_millis(3000)); 
    } 
}
athaniel@nathaniel-virtual-machine:~/rustcoderep/rsadapter$ sudo cargo run
   Compiling rsadapter v0.1.0 (file:///home/nathaniel/rustcoderep/rsadapter)
src/main.rs:166:25: 166:35 error: use of moved value: `globaltest` [E0382]
src/main.rs:166         println!("{:?}",globaltest.clone()); 
                                        ^~~~~~~~~~
<std macros>:2:25: 2:56 note: in this expansion of format_args!
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>)
src/main.rs:166:9: 166:45 note: in this expansion of println! (defined in <std macros>)
src/main.rs:166:25: 166:35 help: run `rustc --explain E0382` to see a detailed explanation
src/main.rs:102:35: 153:3 note: `globaltest` moved into closure environment here because it has type `alloc::arc::Arc<std::sync::mutex::Mutex<collections::string::String>>`, which is non-copyable
src/main.rs:102     let receive_loop = thread::spawn(move || {
src/main.rs:103         
src/main.rs:104       
src/main.rs:105         // Receive loop
src/main.rs:106         for message in receiver.incoming_messages() {
src/main.rs:107             let message: Message = match message {
                ...
src/main.rs:102:35: 153:3 help: perhaps you meant to use `clone()`?
error: aborting due to previous error
use std::{str, thread};

fn main() {
    let mut global_string = "one";

    let child = thread::spawn(move || {
        let payload = b"Some allocated raw data".to_vec();
        let s = str::from_utf8(&payload).unwrap();
        global_string = s;
    });

    println!("{}", global_string);
}
use std::{str, thread};

fn main() {
    let mut global_string = "one".to_string();

    let child = thread::spawn(move || {
        let payload = b"Some allocated raw data".to_vec();
        let s = str::from_utf8(&payload).unwrap();
        global_string = s.to_string();
    });

    println!("{}", global_string);
}
use std::{str, thread};
use std::sync::{Arc, Mutex};

fn main() {
    let global_string = Arc::new(Mutex::new("one".to_string()));
    let inner = global_string.clone();

    let child = thread::spawn(move || {
        let payload = b"Some allocated raw data".to_vec();
        let s = str::from_utf8(&payload).unwrap();
        *inner.lock().unwrap() = s.to_string();
    });

    child.join().unwrap();

    let s = global_string.lock().unwrap();
    println!("{}", *s);
}