if let Ok(socket) = accept_hdr(stream, callback) {
let client_id = Uuid::new_v4().to_string();
let mut mgr_clients = mgr_clients.lock().unwrap();
mgr_clients.insert(client_id.to_owned(), socket);
match socket.read_message() {
Ok(msg) => {
...
},
Err(e) => {
...
}
}
spawn(move || {
...
});
}
Use if let Ok(mut socket) = ....
socket.read_message() error:
cannot move out of a shared reference\nmove occurs because value has type WebSocket<TcpStream>
#tungstenite
after borrow of moved value: socket
\nvalue borrowed here after move
Mate, this ain't Twitter. You can write replies longer than 140 characters or whatever the limit there is.
Please paste the full error and format your code properly.
use std::{net::{TcpListener, TcpStream}, borrow::{Borrow, BorrowMut}};
use tungstenite::{Error, Result, accept_hdr, handshake::server::{Request, Response}, Message, WebSocket, client};
use uuid::Uuid;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use std::thread::{spawn};
use std::sync::{Arc, Mutex};
use http;
#[derive(Serialize, Deserialize)]
struct Inf {
hostname: String,
ip: String,
mac: String,
update_time: i64
}
#[derive(Clone)]
struct App {
fc: Arc<Mutex<AppFc>>
}
type MgrClientItem = Arc<Mutex<HashMap<String, WebSocket<TcpStream>>>>;
#[derive(Clone)]
struct AppFc {
clients: Arc<Mutex<HashMap<String, Inf>>>,
mgr_clients: MgrClientItem
}
const SEC: &'static str = "key";
fn check_access(v: String) -> Result<()> {
if v == SEC {
return Ok(())
}
Err(Error::ConnectionClosed)
}
impl AppFc {
fn handle_client(&self, stream: TcpStream) -> Result<()> {
let mgr_clients = Arc::clone(&self.mgr_clients);
let callback = |req: &Request, response: Response| {
if let Some(token) = req.headers().get(http::header::AUTHORIZATION) {
let access_token = token.to_str().unwrap().to_string();
check_access(access_token).unwrap();
}else {
check_access("".to_owned()).unwrap();
}
Ok(response)
};
if let Ok(mut socket) = accept_hdr(stream, callback) {
let client_id = Uuid::new_v4().to_string();
let mut mgr_clients = mgr_clients.lock().unwrap();
mgr_clients.insert(client_id.to_owned(), socket);
match socket.read_message() {
Ok(msg) => {
},
Err(e) => {
}
}
spawn(move || {
});
}
Ok(())
}
fn send_mgr_clients(&self, clients: &HashMap<String, Inf>, mgr_clients: &HashMap<String, WebSocket<TcpStream>>) {
}
}
impl App {
pub fn new() -> Self {
App {
fc: Arc::new(Mutex::new(AppFc {
clients: Arc::new(Mutex::new(HashMap::new())),
mgr_clients: Arc::new(Mutex::new(HashMap::new())),
})),
}
}
pub fn create_server(&self) {
let server = TcpListener::bind("127.0.0.1:6500").unwrap();
for stream in server.incoming() {
let fc = self.fc.clone();
spawn(move || match stream {
Ok(stream) => {
if let Err(err) = fc.lock().unwrap().handle_client(stream) {
match err {
Error::ConnectionClosed | Error::Protocol(_) | Error::Utf8 => (),
_ => {}
}
}
},
Err(_) => {}
});
}
}
}
fn main() {
let app = App::new();
app.create_server();
}
Thanks for the reminder, I added the full code
And the full error? Formatted the way that cargo build
prints it, please.
error[E0382]: borrow of moved value: socket
--> src\main.rs:56:19
|
52 | if let Ok(mut socket) = accept_hdr(stream, callback) {
| ---------- move occurs because socket
has type WebSocket<TcpStream>
, which does not implement the Copy
trait
...
55 | mgr_clients.insert(client_id.to_owned(), socket);
| ------ value moved here
56 | match socket.read_message() {
| ^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
Rust enforces the single owner principle. The mgr_clients.insert(client_id.to_owned(), socket)
call moves socket
into mgr_clients
. After the move, the socket
variable no longer owns the socket, so you cannot access the socket via the socket
variable.
One thing you could do is to do mgr_clients.get(&client_id)
to get a reference to the socket that is now inside mgr_clients
, but as a general design comment, you should not put an IO resource inside a hash map in the first place — that's almost always a design mistake. One possible alternate design is the actor pattern, where you put a handle to the websocket inside the map, instead of the socket itself. (The linked article uses async/await, but you can use the same pattern in non-async code too.)
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.