2016-11-25 64 views
0

我正在写一个简单的websocket服务器名为BoltServer基于Rust websocket箱(代码是不完整的,我刚刚开始)。我正在使用示例程序作为基础。然而,示例程序不是模块化的(具有很长的方法)。所以我试图把它们分解成结构和方法。我想为每个客户端产生两个线程。一个发送消息,另一个接收消息。所以在这里,我想捕获线程在结构中使用的所有变量,然后在impl中调用run方法。避免封闭 - 封装线程变量结构

extern crate websocket; 
extern crate time; 
extern crate rustc_serialize; 

pub mod ws { 
    use std::thread; 
    use std::sync::{Arc, Mutex}; 
    use std::sync::mpsc; 
    use std::net::ToSocketAddrs; 
    use websocket; 
    use websocket::{Server, Message, Sender, Receiver}; 
    use websocket::server::Connection; 
    use websocket::stream::WebSocketStream; 
    use std::str::from_utf8; 

    struct BoltUser { 
     user_id: u32, 
     my_tx: mpsc::Sender<String>, 
    } 

    struct Broadcaster { 
     my_rx: mpsc::Receiver<String>, 
    } 
    impl Broadcaster { 
     fn new(receiver: mpsc::Receiver<String>) -> Broadcaster { 
      Broadcaster { my_rx: receiver } 
     } 
     fn run(self) { 
      while let Ok(msg) = self.my_rx.recv() { 
       println!("Broadcaster got message: {}", msg); 
      } 
     } 
    } 

    struct SocketReader {} 
    impl SocketReader { 
     fn run(self) {} 
    } 

    struct SocketWriter { 
     my_rx: mpsc::Receiver<String>, 
     sender: Sender, 
    } 
    impl SocketWriter { 
     fn run(self) { 
      while let Ok(message) = self.my_rx.recv() { 
      } 
     } 
    } 

    pub struct BoltServer { 
     address: String, 
     connected_users: Arc<Mutex<Vec<BoltUser>>>, 
    } 
    impl BoltServer { 
     pub fn new(address: &str) -> BoltServer { 
      BoltServer { 
       address: address.to_string(), 
       connected_users: Arc::new(Mutex::new(vec![])), 
      } 
     } 
     fn handshake(&mut self, 
        connection: Connection<WebSocketStream, WebSocketStream>) 
        -> (SocketWriter, SocketReader) { 
      let request = connection.read_request().unwrap(); 
      // println!("thread-> Accepting request..."); 
      let response = request.accept(); 
      let (mut sender, mut receiver) = response.send().unwrap().split(); 
      let (user_tx, user_rx) = mpsc::channel::<String>();//Create a channel for writer 
      let socket_writer = SocketWriter { 
       my_rx: user_rx, 
       sender: sender, 
      }; 
      let socket_reader = SocketReader {}; 
      (socket_writer, socket_reader) 
     } 
     pub fn start(&mut self) { 
      println!("Starting"); 
      let (broadcaster_tx, broadcaster_rx) = mpsc::channel::<String>(); 
      let broadcaster = Broadcaster::new(broadcaster_rx); 
      let handle = thread::Builder::new() 
       .name("Broadcaster".to_string()) 
       .spawn(move || broadcaster.run()); 

      let server = Server::bind(&*self.address).unwrap(); 

      let mut user_id: u32 = 0; 

      // Block and process connection request from a new client 
      for connection in server { 
       user_id = user_id + 1;//Create a new user id 
       let (socket_writer, socket_reader) = self.handshake(connection); 
       thread::Builder::new() 
        .name("Socket writer".to_string()) 
        .spawn(move || socket_writer.run()); 
       thread::Builder::new() 
        .name("Socket reader".to_string()) 
        .spawn(move || socket_reader.run()); 
      } 

      handle.unwrap().join(); 
      println!("Finished"); 
     } 
    } 
} 

下面的代码给出了我想要实现的想法。

// Block and process connection request from a new client 
for connection in server { 
    user_id = user_id + 1;//Create a new user id 
    let (socket_writer, socket_reader) = self.handshake(connection); 
    thread::Builder::new().name("Socket writer".to_string()).spawn(move || { 
     socket_writer.run() 
    }); 
    thread::Builder::new().name("Socket reader".to_string()).spawn(move || { 
     socket_reader.run() 
    }); 
} 

这里我卡在握手方法。我无法通过调用库中的split方法来初始化具有发件人的SocketWriter结构。我正在以下编译错误:

error[E0038]: the trait `websocket::Sender` cannot be made into an object 
    --> src/lib.rs:46:9 
    | 
46 |   sender:Sender, 
    |   ^^^^^^^^^^^^^ the trait `websocket::Sender` cannot be made into an object 
    | 
    = note: method `send_dataframe` has generic type parameters 
    = note: method `send_message` has generic type parameters 

回答

0

错误是告诉你眼前的问题:

46 |   sender:Sender, 
    |   ^^^^^^^^^^^^^ the trait `websocket::Sender` cannot be made into an object 

首先,可变/场不能有一个普通的特征类型(但&Trait可能的话),而且websocket::Sender的性状不是object safe;它具有不能动态工作的通用方法(即,vtable方法必须具有固定类型)。

相反,你必须有一个具体的类型(你也可以使它成为一个通用的结构)。

什么是正确的类型并不明显,所以我想让编译器告诉我。所以首先尝试最简单的可能:

sender:(), 

编译器的一些信息回复:

|      ^^^^^^ expected(), found struct `websocket::client::Sender` 

好吧,让我们插上在:

sender: websocket::client::Sender, 

这给:

46 |   sender: websocket::client::Sender, 
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type arguments, found 0 

好的,这是一个通用类型。下一步尝试:

sender: websocket::client::Sender<()>, 

最后,它给我们的真正类型:

74 |    sender:sender, 
    |      ^^^^^^ expected(), found enum `websocket::WebSocketStream` 

所以最后我们就可以完成SocketWriter

struct SocketWriter { 
    my_rx: mpsc::Receiver<String>, 
    sender: websocket::client::Sender<websocket::WebSocketStream>, 
} 

有一个以下编译错误,因为connection你得到的是一个Result<>所以你需要检查错误(它编译如果我改为self.handshake(connection.unwrap()),但这显然不是最好的实践冰。

+0

谢谢。你是如何找到具体类型的? websocket API文档没有提到它。 – Steve

+0

我已经更新了我的工作答案。 –