2017-12-18 1 views
0

녹을 시작하려하고 일부 조각을 함께 넣고 각각 "소켓"이있는 "클라이언트"의 벡터를 포함하는 "서버"인스턴스를 갖기 위해 노력했습니다.녹슬지 않는 구조체 필드가 ​​소켓에 대해 변경 가능

녹이면 소켓 또는 TcpStream이 변경 가능해야하며 주 루프에서 클라이언트 인스턴스화 이후에 범위를 유지하려면 참조를 빌려야한다는 것을 알고 있습니다.

하지만 TcpStream 필드가 Client 구조체에서 변경 될 수 없다는 문제가 있습니다. 그래서 내 접근 방식이 정확한지 잘 모르겠지만, 평생 파라미터 < 'a>를 사용하여이 문제를 해결하려고 노력했지만, "서버"내부의 "클라이언트"가 평생을 <에 전달하지 않는 또 다른 문제가 생깁니다. 매개 변수.

누군가가이 문제를 해결하거나이 문제/솔루션에 대한 올바른 접근 방식을 보여줄 수 있습니까?

감사합니다.

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(); 
} 

업데이트 :

현재 오류 메시지는 다음과 같습니다

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

업데이트 2 :

이 지금은 솔루션이 목표에 가까운/조금 더 나은 생각합니다. 하지만 여전히 스레드에 문제가 있습니다. 정적 컨텍스트 외부에 생성하십시오.

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(); 
} 

오류 [E0477] : 유형 [[email protected]/main.rs:38:23: 40:10 self:&mut Server, client:Client] 필요한 수명을 충족하지 않는

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

에 대한보다 구체적인주십시오 당신의 발행물. 좋은 [MCVE]는 일반적으로 컴파일러에서 그대로 복사 된 오류 메시지를 포함합니다. –

+1

뻔뻔스럽게도이 코드에는 * 많은 * 문제가 있습니다. 예를 들면 : 당신이 뭔가를 이동 한 후에 참조를 취하고, 로컬 변수에 대한 참조를 쓰레드에 전달하려한다면, 아마도 많은 장소에서'& self' 대신에'mut mut'를 원할 것입니다. [* The Rust Programming Language *] (https://doc.rust-lang.org/book/secondedition/)를 읽으셨습니까? 적극 추천합니다. 그 수명이하는 일이 아니다 - * 나는이 수명 매개 변수'<'a>'*을 사용하여 해결하기 위해 노력했다. 다시,이 책은 수명이 무엇인지 설명 할 것입니다. 격렬하게 대충 빠져서 녹을 배우는 것이 쉽지 않거나 재미 있지 않습니다. – Shepmaster

+0

안녕하세요 @ E_net4, 더 자세한 정보를 제공하지 않아 죄송합니다. 지금 오류 메시지가 추가됩니다. –

답변

0

지금은 전체 문제를 해결할 수 있었다 :

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

식별자가 사용되지 않는 한 식별자를'_'로 시작하지 마십시오. 이것은 멤버 변수와 메서드 사이의 이름 충돌을 피할 필요가있는 C++가 아닙니다. – Shepmaster

관련 문제