2017-05-29 45 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()方法中的所有內容,這意味着您可以將它傳遞給Service對象實例化,然後在call()期間握手將可用。