2016-11-25 12 views
0

私は、Rust websocket crateに基づいてBoltServerという名前のシンプルなwebsocketサーバーを作成しています(コードは不完全です。私はサンプルプログラムをベースとして使用しています。しかし、サンプルプログラムはモジュール化されていません(非常に長いメソッドを持っています)。だから私はそれらを構造体とメソッドに分解しようとしています。私は各クライアントのために2つのスレッドを生成したい。 1つはメッセージを送信し、もう1つはメッセージを受信します。ここでは、スレッドで使用されるすべての変数を構造体に取り込み、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メソッドは固定タイプを持つ必要があります)。

代わりに、具体的な型(generic構造体にすることもできます)が必要です。

正しいタイプが何であるかはっきりしていないので、コンパイラに教えてもらいたいです。だから、最初の最も簡単な方法を試してください。

sender:(), 

コンパイラはいくつかの情報を返信:

sender: websocket::client::Sender, 

与えること:

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

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

[OK]を、のがでていることプラグましょう

これは一般的なタイプです。次のtry:だから最後に私たちはSocketWriterを終えることができる

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

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

最後に、それは私たちに本当のタイプを与える

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

あなたが得るconnectionがあるので、以下のコンパイルエラーがありますResult<>エラーをチェックする必要があります(self.handshake(connection.unwrap())に変更するとコンパイルされますが、それは明らかにベストプラクティスではありません氷。

+0

ありがとうございます。どのように具体的なタイプを見つけましたか? websocket APIドキュメントには触れられていませんでした。 – Steve

+0

私は私の仕事の答えを更新しました。 –

関連する問題