event-streamでデータストリーミングしてみる

あすかです。

夏コミC92受かりました。
ただしジャンルは3日目の「創作(少年)」です。技術系ではないです。
あとは適当に探してください。

ASP.NETで、ストリーミングをやります。
ストリーミングといっても、受信する方のおはなしではありません。両方です。

また、送信するのはただのテキストデータです。
ビデオとかはやりませんが、この記事を応用して、例えば映像をBASE643に変換するとかすればできるかもしれません。
C#オブジェクトのやり取りも、JSONが使えます。

今回は、ASP.NET側からストリーミングのデータを送信し、Console側でそれを受信します。
自給自足、自作自演です。

送信側(ASP.NET Core)

送信します。

送信します。

送信します。

送信の基本はこれです。

コントローラクラスに、このメソッドを入れるだけです。
あとは、ブラウザ(後述)を使ってこのページに接続すると、ストリーミングが行われます。

「こんにちは」と表示された後、3秒後に「きゅうりでつっこむぞ」が表示されますね。

ストリーミング対応しているブラウザ

現状、event-streamヘッダによるストリーミングに対応しているブラウザは、Google Chromeだけです。
他のブラウザは全滅です。

Microsoft Edge 40.15063

f:id:kmynews:20170611105326p:plain

Mozilia Firefox 53.0.3

f:id:kmynews:20170611105421p:plain

Google Chrome 58.0.3029

f:id:kmynews:20170611105634p:plain

というわけで、ストリーミングのテストを行うさいは大正義Google Chromeを使いましょう。いや使えコンチキショー

ストリーミングには有効期限がある

ここでもう一度ソースとGoogle Chromeの動きを確認してみましょう。
ページを表示している間、Google Chromeのタブの左側がくるくるしています。
これは、「このページはまだロードの途中ですよ」、つまり「新しいデータを取り込んでいる途中」=「ストリーミングなう」ということをあらわしています。

f:id:kmynews:20170611110417p:plain

ストリーミングデータを受け取れるのは、くるくるしている間だけです。
くるくるが終わった後にサーバが新しいデータを送信しても、ブラウザ側は受け取れません。
それでは、このくるくるは何なのかというと、Task.Delayで3秒待っている部分ですね。アクションメソッドの実行が終わるまでの間、この状態になります。

全員に同じ内容のストリーミングを配信するには

今までやったのは、現在の接続に対するストリーミングです。
つまり、接続が始まってから3秒後だとか、5秒後だとか、そういう、現在の接続が開始されたタイミングでしか配信を行えていません。

もしも、同じデータを複数の人に同時に配信したくなったら?
もちろん、複数の人達の接続時間はばらばらです。データも全く同じである必要があります。

答えは単純で、接続ごとに得られるHttpResponseをどこかのコレクションにまとめておいて、データを送信する時に全てのHttpResponseに対して送出すればいいのです。
それをおこなうクラスがこれです。

有効な接続に対してデータの送信をおこなうクラス

SendMessageAsyncメソッドで、ストリーミングに来たお客さんたちに、データを送信しています。
必要最低限のことしかしていないのですが、接続が切れた時にResponseへの書き込みが例外を出すので、エラーハンドリングは必須です。

接続を追加するメソッド(コントローラのGETアクション)

閲覧者がブラウザのページを開いた時、ASP.NET側は、接続をコレクションに追加するだけでいいです。
これで終わりです。あとはストリーミングを20秒続けるよう処理をしています。

これで、SendMessageAsyncメソッドを実行した時、この接続に対してデータの送出が行われるようになります。

データを送信するメソッド(コントローラのstaticコンストラクタ)

定期的にデータを送信するようにしています。

実行!

データが6回、こっちにまわってきました。
20秒以内に3秒ごとですから、妥当な数字ですね。

f:id:kmynews:20170611112718p:plain

受信側(.NET Frameworkコンソールアプリ)

受信する方はどうすればいいでしょうか。
これも、たったこれだけのコードで十分です。

ユーザがEnterキーを押すと、新しい接続が開始されるようになっています。
あとは、接続が続いている間(20秒間)、ストリーミングでとってきたデータをコンソールに表示するだけです。

f:id:kmynews:20170611113210p:plain

データが表示されましたね。
ここで、試しにEnterキーを連打してみます。

f:id:kmynews:20170611113305p:plain

簡易的ですが、複数の接続に対して同時にデータを受信していることが確認できました。

まとめ

暑いの嫌い