use std::io::{self, Read, Write};
use std::net::{TcpListener, TcpStream};
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use serde_derive::{Deserialize, Serialize};
use crate::devices;
pub struct IotServer {
ip:String,
port:u32,
listener:TcpListener,
handles:Vec<thread::JoinHandle<()>>
}
impl IotServer {
pub fn open(ip:&str, port:u32) -> io::Result<Self> {
let listener = TcpListener::bind(format!("{}:{}", &ip, &port))?;
Ok(IotServer {
ip:ip.to_string(),
port,
listener,
handles:vec![],
})
}
pub fn start(&mut self) {
println!("Starting IOT Server On IP:{} PORT:{}...", self.ip, self.port);
self.listen();
}
pub fn listen(&mut self) {
for stream in self.listener.incoming() {
match stream {
Err(_) => {
},
Ok(mut ok_stream) => {
let handle = thread::spawn(move || {
self.handle_request(ok_stream);
});
self.handles.push(handle);
}
}
}
}
pub fn handle_request(&self, mut stream:TcpStream) {
let mut buffer = [0; 1024]; // Buffer size
stream
.read(&mut buffer)
.expect("Failed To Read From Client"); // Reads stream data then puts it into the buffer
// Turns buffer data into string but handles messy data
let request = String::from_utf8_lossy(&buffer[..]);
println!("Received Request {request}");
let response = "Hello, Client".as_bytes();
stream.write(response).expect("Failed To Respond");
}
pub fn shutdown(&mut self) {
println!("Shutting Down Server...");
for handle in self.handles.drain(..) {
handle.join().unwrap();
}
println!("Server Shut Down");
}
}
#Self and threading
10 messages · Page 1 of 1 (latest)
This is the Error Message
error[E0521]: borrowed data escapes outside of method
36 | pub fn listen(&mut self) {
| ---------
| |
| `self` is a reference that is only valid in the method body
| let's call the lifetime of this reference `'1`
...
42 | let handle = thread::spawn(move || {
| ^
43 | | self.handle_request(ok_stream);
44 | | });
| | ^
| | |
| |______________________`self` escapes the method body here
| argument requires that `'1` must outlive `'static`
error[E0505]: cannot move out of `self` because it is borrowed
36 | pub fn listen(&mut self) {
| --------- binding `self` declared here
37 | for stream in self.listener.incoming() {
| ------------- borrow of `self.listener` occurs here
...
42 | let handle = thread::spawn(move || {
| ^^^^^^^ move out of `self` occurs here
43 | self.handle_request(ok_stream);
| ---- move occurs due to use in closure
error[E0382]: borrow of moved value: `self`
--> src\server.rs:45:21
|
36 | pub fn listen(&mut self) {
| --------- move occurs because `self` has type `&mut IotServer`, which does not implement the `Copy` trait
42 | let handle = thread::spawn(move || {
| ------- value moved into closure here
43 | self.handle_request(ok_stream);
| ---- variable moved due to use in closure
44 | });
45 | self.handles.push(handle);
| ^^^^^^^^^^^^ value borrowed here after move
are you familiar with closures and captures yet?
not like a deep level necessarily, but have you at least read the relevant chapter in the book
A closure is just a function that can use local variables from where its defined but im getting conflicts with ownership right now
This is my current progress
pub fn start(&mut self) {
println!("Starting IOT Server On IP:{} PORT:{}...", self.ip, self.port);
self.listen();
}
pub fn listen(&mut self) {
let copy = Arc::new(Mutex::new(&self));
for stream in self.listener.incoming() {
match stream {
Err(_) => {
},
Ok(mut ok_stream) => {
let handle = thread::spawn(|| {
self.handle_request(ok_stream);
});
self.handles.push(handle);
}
}
}
}
at risk of spoiling it, see if you can change something about handle_request
what make it not use self
yeah, it can just be an associated function - it's related to IotServer so it makes sense to put it in the namespace, but it doesn't make sense to borrow the IotServer when the function doesn't need to use that borrow
borrowing from other lang terminology, it causes an ownership problem as an instance method, but as a static method you can call it from other threads no problem