###### 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()
}
```