event-streamでデータストリーミングしてみる
あすかです。
夏コミC92受かりました。
ただしジャンルは3日目の「創作(少年)」です。技術系ではないです。
あとは適当に探してください。
ASP.NETで、ストリーミングをやります。
ストリーミングといっても、受信する方のおはなしではありません。両方です。
また、送信するのはただのテキストデータです。
ビデオとかはやりませんが、この記事を応用して、例えば映像をBASE643に変換するとかすればできるかもしれません。
C#オブジェクトのやり取りも、JSONが使えます。
今回は、ASP.NET側からストリーミングのデータを送信し、Console側でそれを受信します。
自給自足、自作自演です。
送信側(ASP.NET Core)
送信します。
送信します。
送信します。
送信の基本はこれです。
コントローラクラスに、このメソッドを入れるだけです。
あとは、ブラウザ(後述)を使ってこのページに接続すると、ストリーミングが行われます。
「こんにちは」と表示された後、3秒後に「きゅうりでつっこむぞ」が表示されますね。
ストリーミング対応しているブラウザ
現状、event-stream
ヘッダによるストリーミングに対応しているブラウザは、Google Chromeだけです。
他のブラウザは全滅です。
Microsoft Edge 40.15063
Mozilia Firefox 53.0.3
ストリーミングには有効期限がある
ここでもう一度ソースとGoogle Chromeの動きを確認してみましょう。
ページを表示している間、Google Chromeのタブの左側がくるくるしています。
これは、「このページはまだロードの途中ですよ」、つまり「新しいデータを取り込んでいる途中」=「ストリーミングなう」ということをあらわしています。
ストリーミングデータを受け取れるのは、くるくるしている間だけです。
くるくるが終わった後にサーバが新しいデータを送信しても、ブラウザ側は受け取れません。
それでは、このくるくるは何なのかというと、Task.Delay
で3秒待っている部分ですね。アクションメソッドの実行が終わるまでの間、この状態になります。
全員に同じ内容のストリーミングを配信するには
今までやったのは、現在の接続に対するストリーミングです。
つまり、接続が始まってから3秒後だとか、5秒後だとか、そういう、現在の接続が開始されたタイミングでしか配信を行えていません。
もしも、同じデータを複数の人に同時に配信したくなったら?
もちろん、複数の人達の接続時間はばらばらです。データも全く同じである必要があります。
答えは単純で、接続ごとに得られるHttpResponse
をどこかのコレクションにまとめておいて、データを送信する時に全てのHttpResponse
に対して送出すればいいのです。
それをおこなうクラスがこれです。
有効な接続に対してデータの送信をおこなうクラス
SendMessageAsync
メソッドで、ストリーミングに来たお客さんたちに、データを送信しています。
必要最低限のことしかしていないのですが、接続が切れた時にResponse
への書き込みが例外を出すので、エラーハンドリングは必須です。
接続を追加するメソッド(コントローラのGETアクション)
閲覧者がブラウザのページを開いた時、ASP.NET側は、接続をコレクションに追加するだけでいいです。
これで終わりです。あとはストリーミングを20秒続けるよう処理をしています。
これで、SendMessageAsync
メソッドを実行した時、この接続に対してデータの送出が行われるようになります。
データを送信するメソッド(コントローラのstaticコンストラクタ)
定期的にデータを送信するようにしています。
実行!
データが6回、こっちにまわってきました。
20秒以内に3秒ごとですから、妥当な数字ですね。
受信側(.NET Frameworkコンソールアプリ)
受信する方はどうすればいいでしょうか。
これも、たったこれだけのコードで十分です。
ユーザがEnterキーを押すと、新しい接続が開始されるようになっています。
あとは、接続が続いている間(20秒間)、ストリーミングでとってきたデータをコンソールに表示するだけです。
データが表示されましたね。
ここで、試しにEnterキーを連打してみます。
簡易的ですが、複数の接続に対して同時にデータを受信していることが確認できました。
まとめ
暑いの嫌い