書きかけだけど、途中で行き詰まった...
このまま下書きで公開しないまま、そっ閉じでもいいんだけど...
何で行き詰まったかというと、WebSocketでクライアント側から任意のタイミングでサーバーへ通信を仕掛けるのはわかるんだけど、サーバー側からクライアントへ任意のタイミングで通信する方法がよくわからず...という感じ
とりあえず、事前調査的なことが以下
ブラウザとサーバーで双方向の通信を実現する仕組みは、昔は、JavaScriptでポーリングして、とか、comet とかいう呼び名だったり... 最近は、Websocketって言葉をよく見るなーくらいの知識
双方向通信の技術についての全般的なお話は、以下を参考にした
そして Websocket のクライアント側の実装を先日やった
今回やりたいことは表題の通りで、サーバー側もクライアント側も自分で実装することになるため、1からお勉強...
色々見て、以下がスッと理解できた
上記で理解が深まったのが、どちらかというとクライアント側かな...
ブラウザ / HTML+JavaScript 側の実装で、JavaScript で WebSocket のインスタンス?を作成して、サーバーからのメッセージを受け取った時の動作/挙動を記述する
で、サーバー側は、クライアントが増えたときにメッセージを送出するような実装がサンプルとして記述されていた。
やりたいことは、サーバー側は任意のタイミングでメッセージを送出できるようにして、クライアント側はメッセージの受け取り時に画面の表示をリフレッシュして、クライアント側からの更新処理も実装したい。
若干難しいことが最初に書かれているけど... 以下も仕組みの理解に役立った
Dockerやuwsgiは、ちょっと余計な情報だけど...
クライアント側の実装が使えそうで、ボタンをクリックした時にWebSocketを開始して、コネクションを開始した時にメッセージをクライアント側からサーバーに創出して、サーバー側はメッセージを受け取ったら、そのまま、その内容をクライアントに送出するようになって、サーバー側からのメッセージを受け取ってクライアント側ではプロンプトにそれを表示する
クライアント側のoncloseというイベントが、どのタイミングで発生するのかがわからない...
今回組み込もうとしているプログラムでは、Pythonのresponderというフレームワークを利用しているので、以下の実装例は参考になる。
サーバー側の実装が参考になる
@api.route('/ws', websocket=True)
async def websocket(ws):
await ws.accept()
key = ws.headers.get('sec-websocket-key')
clients[key] = ws
try:
while True:
msg = await ws.receive_text()
for client in clients.values():
await client.send_text(msg)
except:
await ws.close()
del clients[key]
- URLの形式を指定する時に WebSocket であることを引数で宣言
- 処理メソッドは async で非同期、引数にWebSocketの何かを受け取る
クライアント側からサーバーにデータを送出する時のトリガーが、エンターを押した時となっていて、それは使えるかも
window.onload = function () {
textbox.addEventListener('keypress', function (e) {
// エンターキーが押された場合メッセージを送信
if (e.keyCode == 13) {
ws.send(textbox.value);
textbox.value = "";
}
});
}
で、ここまで調べていて、そもそもがresponderでシンプルなページ描画についても知らないことに気づいたのでw その辺りの情報もピックアップ
ページ描画だけじゃないけど、以下は一通りのことが書かれていて色々参考になる
-
[第0回] Responderを使ってDjangoチュートリアルをやってみた【初期セットアップ編】
- Jinja2テンプレートを使ってレスポンスを返す時に、
resp.text
で返していてHTMLでちゃんと描画されず一瞬悩んだけどresp.content
で返してあげないとね... ということに、ここを読んで気づいた
- Jinja2テンプレートを使ってレスポンスを返す時に、
-
[第1回] Responderを使ってDjangoチュートリアルをやってみた【プロジェクト作成編】
- ビューのルーティングを記述する urls.py と、webサーバーを起動する run.py にファイルを分割
- bootstrapを使ったテンプレート定義
-
[第2回:前編] Responderを使ってDjangoチュートリアルをやってみた【データベース・モデル構築編】
- SQLAlchemyを使った実装例
-
[第2回:後編] Responderを使ってDjangoチュートリアルをやってみた【データベース・モデル構築編】
- Cookieを利用したログイン認証の実装例