2017-12-18 6 views
0

Ich versuche, mit Rust zu beginnen, und versuchte, einige Stücke zusammen zu setzen und eine "Server" -Instanz zu haben, die einen Vektor von "Clients" enthält, wo jeder von ihnen einen Sockel hat.Rust Struct Feld veränderbar für Socket

Ich verstehe, dass in Rust der Socket oder TcpStream veränderbar sein muss, und dass ich die Referenz ausleihen muss, um den Bereich nach der Client-Instantiierung in meiner Hauptschleife zu behalten.

Aber ich konfrontiert das Problem, dass mein TcpStream-Feld möglicherweise nicht in der Client-Struktur veränderbar sein. Ich bin mir also nicht sicher, ob mein Ansatz korrekt ist, aber ich habe versucht, dies mit dem Lebensdauerparameter < 'a> zu lösen, was mich jedoch zu einem anderen Problem führt, bei dem mein "Client" innerhalb von "Server" die <' a> Lebenszeit nicht übersteht Parameter.

Kann jemand mir helfen, dieses Problem zu lösen oder mir den richtigen Ansatz für dieses Problem/Lösung zeigen?

Danke.

use std::net::*; 
use std::io::Write; 
use std::thread; 
use std::time::Duration; 

struct Client<'a> { 
    socket: &'a mut TcpStream, 
    addr: SocketAddr 
} 

struct Server { 
    clients: Vec<Box<Client>> 
} 

impl Server { 
    pub fn new() -> Server { 
     Server{clients: Vec::new()} 
    } 

    fn write(&self, stream: &mut TcpStream) { 
     let mut counter: u32 = 0; 
     counter += 1; 
     stream.write(counter.to_string().as_bytes()).unwrap(); 
     thread::sleep(Duration::from_secs(1)); 
    } 

    fn client_thread(&self, client: &mut Client) { 
     self.write(&mut client.socket); 
    } 

    fn add_client(&self, socket: &mut TcpStream, addr: SocketAddr) { 
     let mut client = Client { 
      socket: socket, 
      addr: addr 
     }; 

     self.clients.push(Box::new(client)); 

     self.client_thread(&mut client); 
    } 

    pub fn server_loop(&self) { 
     let listener = TcpListener::bind("127.0.0.1:5001").unwrap(); 

     loop { 
      match listener.accept() { 
       Ok((mut socket, addr)) => { 
        println!("new client: {:?}", addr); 

        thread::spawn(move || loop { 
         self.add_client(&mut socket, addr); 
        }); 
       }, 
       Err(e) => println!("couldn't get client: {:?}", e), 
      } 
     } 
    } 
} 

fn main() { 
    let mut server = Server::new(); 
    server.server_loop(); 
} 

Update:

Die aktuelle Fehlermeldung lautet:

clients: Vec<Box<Client>> 
        ^^^^^^ expected lifetime parameter 

Update 2:

Jetzt denke ich, die Lösung ein wenig besser/näher an das Ziel. Aber ich habe immer noch ein Problem mit dem Thread: außerhalb des statischen Kontexts spawnen.

use std::net::*; 
use std::io::Write; 
use std::thread; 

struct Client { 
    socket: TcpStream 
} 

struct Server { 
    clients: Vec<Box<Client>> 
} 

impl Server { 
    fn new() -> Server { 
     Server{clients: vec![]} 
    } 

    fn write(&mut self, stream: &mut TcpStream) { 
     let mut counter: u32 = 0; 
     stream.write(counter.to_string().as_bytes()).unwrap(); 
    } 

    fn client_loop(&mut self, client: &mut Client) { 
     loop { 
      self.write(&mut client.socket); 
     } 
    } 

    fn add_client(&mut self, s: TcpStream) { 
     let mut client = Client{ 
      socket: s 
     }; 

     self.clients.push(Box::new(client)); 

     println!("New client: {}", client.socket.peer_addr().unwrap()); 

     thread::spawn(move || { 
      self.client_loop(&mut client); 
     }); 
    } 

    pub fn server_loop(&mut self) { 
     let listener = TcpListener::bind("127.0.0.1:5001").unwrap(); 

     loop { 
      match listener.accept() { 
       Ok((socket, _addr)) => { 
        self.add_client(socket); 
       }, 
       Err(e) => println!("Couldn't get client: {}", e), 
      } 
     } 
    } 
} 

fn main() { 
    let mut server = Server::new(); 
    server.server_loop(); 
} 

Fehler [E0477]: der Typ [[email protected]/main.rs:38:23: 40:10 self:&mut Server, client:Client] erfüllt nicht die erforderliche Lebensdauer

--> src/main.rs:38:9 
    | 
38 |   thread::spawn(move || { 
    |   ^^^^^^^^^^^^^ 
    | 
    = note: type must satisfy the static lifetime 
+1

Bitte spezifischere über Ihre Problem. Ein gutes [MCVE] enthält normalerweise die Fehlermeldungen, die wörtlich vom Compiler kopiert werden. –

+1

Blendenderweise gibt es * viele * Dinge, die mit diesem Code nicht stimmen. Zum Beispiel: Sie nehmen einen Verweis auf etwas, nachdem Sie es verschoben haben, Sie versuchen, einen Verweis auf eine lokale Variable zu einem Thread zu übergeben, möchten Sie wahrscheinlich '& mut self' anstelle von '& self' an vielen dieser Orte, etc .. Haben Sie lesen [* The Rust Programming Language *] (https://doc.rust-lang.org/book/second-edition/)? Es ist sehr zu empfehlen. * Ich habe versucht, dies zu lösen, indem ich den Lebensdauer-Parameter '<'a>' * verwende - das ist nicht die Lebenszeit. Wiederum wird das Buch erklären, was Lebenszeiten sind. Es ist nicht einfach oder lustig, Rust zu lernen, indem man wild um sich schlägt. – Shepmaster

+0

Hi @ E_net4, tut mir leid, dass ich keine besseren Details zur Verfügung stelle, es wird jetzt die Fehlermeldung hinzugefügt. –

Antwort

0

konnte ich nun das Gesamtproblem lösen:

use std::net::*; 
use std::io::Write; 
use std::thread; 

struct Client { 
    socket: TcpStream, 
} 

impl Client { 
    pub fn write(&mut self) { 
     let counter: u32 = 0; 
     self.socket.write(counter.to_string().as_bytes()).unwrap(); 
    } 
} 

struct ClientThread { 
    inner: Client, 
} 

impl ClientThread { 
    pub fn client_loop(&mut self) { 
     let client = &mut self.inner; 

     client.write(); 
    } 
} 

struct Server { 
    _clients: Vec<Box<Client>>, 
} 

impl Server { 
    fn new() -> Server { 
     Server { _clients: vec![] } 
    } 

    fn add_client(&mut self, s: TcpStream) { 
     let client = Client { socket: s }; 

     println!("New client: {}", client.socket.peer_addr().unwrap()); 

     self._clients.push(Box::new(client)); 

     let mut client_thread = ClientThread { inner: client }; 

     thread::spawn(move || loop { 
      client_thread.client_loop(); 
     }); 
    } 

    pub fn server_loop(&mut self) { 
     let listener = TcpListener::bind("127.0.0.1:5001").unwrap(); 

     loop { 
      match listener.accept() { 
       Ok((socket, _addr)) => { 
        self.add_client(socket); 
       } 
       Err(e) => println!("Couldn't get client: {}", e), 
      } 
     } 
    } 
} 

fn main() { 
    let mut server = Server::new(); 
    server.server_loop(); 
} 
+0

Beginnen Sie nicht mit '_', wenn sie nicht unbenutzt sind. Dies ist kein C++, bei dem Namenskonflikte zwischen Membervariablen und Methoden vermieden werden müssen. – Shepmaster