2017-05-29 7 views
1

tokio-protoクレートを使用する方法、特に接続が確立されたときのハンドシェイクを理解しています。私はofficial documentation作業から例を持っている:tokio-proto接続ハンドシェイクから情報を取り出す方法は?

impl<T: AsyncRead + AsyncWrite + 'static> ClientProto<T> for ClientLineProto { 
    type Request = String; 
    type Response = String; 

    /// `Framed<T, LineCodec>` is the return value of `io.framed(LineCodec)` 
    type Transport = Framed<T, line::LineCodec>; 
    type BindTransport = Box<Future<Item = Self::Transport, Error = io::Error>>; 

    fn bind_transport(&self, io: T) -> Self::BindTransport { 
     // Construct the line-based transport 
     let transport = io.framed(line::LineCodec); 

     // Send the handshake frame to the server. 
     let handshake = transport.send("You ready?".to_string()) 
      // Wait for a response from the server, if the transport errors out, 
      // we don't care about the transport handle anymore, just the error 
      .and_then(|transport| transport.into_future().map_err(|(e, _)| e)) 
      .and_then(|(line, transport)| { 
       // The server sent back a line, check to see if it is the 
       // expected handshake line. 
       match line { 
        Some(ref msg) if msg == "Bring it!" => { 
         println!("CLIENT: received server handshake"); 
         Ok(transport) 
        } 
        Some(ref msg) if msg == "No! Go away!" => { 
         // At this point, the server is at capacity. There are a 
         // few things that we could do. Set a backoff timer and 
         // try again in a bit. Or we could try a different 
         // remote server. However, we're just going to error out 
         // the connection. 

         println!("CLIENT: server is at capacity"); 
         let err = io::Error::new(io::ErrorKind::Other, "server at capacity"); 
         Err(err) 
        } 
        _ => { 
         println!("CLIENT: server handshake INVALID"); 
         let err = io::Error::new(io::ErrorKind::Other, "invalid handshake"); 
         Err(err) 
        } 
       } 
      }); 

     Box::new(handshake) 
    } 
} 

しかし、公式ドキュメントは、ステートフル情報なしで握手を言及します。ハンドシェイクから有用なデータを取得して保存する一般的な方法はありますか?

たとえば、(接続が確立された後の最初のメッセージの)ハンドシェイク中にサーバが後でクライアントで使用する必要があるキーを送信した場合、ClientProto実装ではそのキーをどのように調べる必要がありますか?そしてそれはどこに保存すべきですか?

+0

私は何かが欠けているに違いないと思います - あなたが探している "キー"の可変的な "ハンドシェイク"ではありませんか?これは既にこの関数から返されているので、あなたはちょうど... *使用していますか? – Shepmaster

+0

'bind_transport()'から返される 'handshake'変数は、まだ実行されていないハンドシェーク手続きを含む未来です。私はこのハンドシェイク中にいくつかの重要な価値を読んで、このクライアントから後で行くリクエストでそれを使う必要があります。基本的には、ハンドシェイクの未来が完了した後に値を取得して保存する必要があります。私のプロトコルのために自分自身の 'BindClient'特性を実装すること以外はこれを行う方法がありません。正しい方法であるとは確信していません... –

答えて

1

あなたはClientLineProtoにフィールドを追加することができますので、これは動作するはずです:

pub struct ClientLineProto { 
    handshakes: Arc<Mutex<HashMap<String, String>>> 
} 

を、必要に応じて、あなたはそれを参照し、データを格納することができます

let mut handshakes = self.handshakes.lock(); 
handshakes.insert(handshake_key, "Blah blah handshake data") 

は、アクセスのこの種がbind_transport()に働くだろう物を保管するためのものです。そして、main()関数にArc::Mutex::HashMapを作成すると、serve()メソッドのすべてにアクセスできるようになります。つまり、サービスオブジェクトのインスタンス化に渡すことができ、call()の間にハンドシェイクが利用可能になります。

関連する問題