###### tags: `WebSocket` `server` `Rust` # Socket通信について #2 # Websocket Server Rustの ws-rs でやっていく ## ws-rs ssl対応 feature = 機能 Cargo.toml で ssl機能を使うようにする ```toml= [dependencies.ws] version = "*" features = ["ssl"] ``` これで、ws-rs のサーバーもクライアントも **wss**で通信を行うようになる # サーバーソケット作成 ## listen関数 これを使うだけで、ライフサイクルのうちの以下を実行する。 - create - bind - listen ```rust= extern crate ws; if let Err(error) = ws::listen("localhost:5000", |out|{ move |msg| { plintln!("{}", msg); out.send(msg) } }) ``` out: Sender = sendとかbroadcastとかのメソッドを提供するオブジェクト move |msg| {}: Handler = メッセージが来たときに実行されるコールバック msg: Message = 送られてきたデータの入っているenum型。値を取り出す方法により、 text か binary のどちらかとして扱える。 ## listen関数の定義 ```rust= pub fn listen<A, F, H>(addr: A, factory: F) -> Result<()> where A: ToSocketAddrs + Debug, F: FnMut(Sender) -> H, H: Handler, ``` - addr : 普通にアドレス。url:portの文字列でok - factory : ハンドラを作って返すクロージャー - FnMut : 引数をmut型で取るクロージャー。コールバック - ws::Sender : WebSocket通信の接続の出力機能を表現するオブジェクト - ws::Handler: wsライブラリのコアとなるtrait。websocketアプリのビジネスロジック実装部分 - Handler : msgを受け取って何かをするクロージャー ## Sender exampleの out のこと on_message や on_request, on_responseのときは つながっているクライアントを識別して個別に送信できる ### サーバー - send(msg) : 個別のクライアントに返信 - broadcast(msg) : すべての接続にメッセージを送信。 - 注意 : 単なるサーバーとして動作しているなら良いが、サーバーとクライアントを兼ねていると別のWebSocketにまで送信してしまう - close() : 個別の接続を切断する - shutdown() : 全部の接続を切断する。 ## Handler ハンドラーを実装するためのトレイト Handlerトレイトが実装された構造体は、Factoryとして扱える。 サーバーやクライアントは、 on_open や on_message などの イベントに対しハンドラを設定する ## Factory - ws::listen() : wsサーバーとしてアクセスを受け付ける関数 - ws::connect() : wsクライアントとして、サーバーへ接続する関数 などの引数に使える (F: factory) ハンドラーを製造して返すのでFactory Factory -> Handler 基本的には、外部からSenderオブジェクトを受け取り、 Handler内部のSenderにバインドして、ハンドラを返すイメージ on_messageだけを行うFactroyを、クロージャーで代用することもできる。 ### Message exampleのmsgのこと。 そのままStringとして使える。 # カスタムサーバー (or クライアント) WebSocket通信には様々なイベントが有る - on_message - on_open - on_close - on_error messageが来たときだけではなく、様々な状況でハンドラを実行したいなら、 独自のサーバー構造体を作成し、Handlerトレイトを out: ws::Sender プロパティは、送信の出口を指定 ```rust= extern crate ws; use ws::{listen, Handler, Sender, Result, Message, CloseCode}; struct Server { out: Sender, } impl Handler for Server { fn on_message(&mut self, msg: Message) -> Result<()> { self.out.send(msg) } fn on_close(&mut self, code: CloseCode, reason: &str) { match code { CloseCode::Normal => println!("The client is done with the connection."), CloseCode::Away => println!("The client is leaving the site."), _ => println!("The client encountered an error: {}", reason), } } } fn main() { listen("127.0.0.1:3012", |out| Server { out: out } ).unwrap() } ```