質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.77%

Python - Flask socketIOで更新すると通信が重複する問題

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 4,046

score 115

 開発環境

MacOS Sierra
バージョン:Python 3.6
フレームワーク:Flask

 やっていること

ページを起動すると、websocketを使いサーバー側から1秒に一回数字を受け取り、リアルタイムで表示させる。

app.py

from flask import Flask,render_template, session, request,redirect
from flask_socketio import SocketIO, emit, disconnect

async_mode = None

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hoge'
socketio = SocketIO(app, async_mode=async_mode)

# 毎秒1ずつカウントし、my_responseにemitする
def background():
    count = 0
    while True:
        socketio.sleep(1)
        count += 1
        socketio.emit('my_response', {'data': count}, namespace='/test')

@app.route('/')
def index():
    socketio.start_background_task(target=background)
    return render_template('index.html')

if __name__ == '__main__':
    socketio.run(app, host='127.0.0.1', port=5000, debug=True)

index.html

layout.htmlは割愛します

{% extends "layout.html" %}
{% block script %}
<script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
<script type="text/javascript" charset="utf-8">
    $(document).ready(function() {
      namespace = '/test';
      var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
      var title = document.title;

      socket.on('my_response', function(msg) {
          $('#field').append(msg.data);
      });

    });
</script>
{% endblock %}

{% block body %}

<section id="field"></section>
{% endblock %}

これで以下の画像のように、毎秒1ずつ数字が追加され表示されるのですが、
イメージ説明

 困っていること

ページをリロードすると、複数のソケット接続(?)が発生するためか、リロードした回数分おかしな表示が増えていってしまいます。

例)カウントが15の時点でリロードすると、
1回目の接続の続き:15,16,17...
2回目で発生した接続:1,2,3...
この両方が重なり、以下のように表示されてしまいます。
115216317...

小生、websocketの知識が乏しく、Javascriptもいじっては修正の繰り返しでなんとかやっています。

リロードすると、接続状態をリセットし、カウントを初期から単一接続で行う
方法がわからず困っています。

わかりにくい説明&ニッチな問題で申し訳ありませんが、どなたかわかる方がいらっしゃいましたら、ご教授いただきたく思います。

よろしくお願いいたします。

 追記:やってみたこと

更新した場合に「/hoge」にリダイレクトさせ、以降はそちらのみのアクセスに強制・・・みたいなことをやれば、start_backgroundの回避はできましたが、根本的な解決にはなっていません。

@app.route('/')
def index():
    socketio.start_background_task(target=background)
    return render_template('index.html')

@app.route('/hoge')
def index():
    return render_template('index.html')
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

リロードすると、websocketのコネクションも別のものになります。
そのため、貴殿が提示された解決方法も一つの手法かと思います。
あるいは、一回のコネクションでセッションを取得し、リロード時にはきちんと終了処理をした上で、最新のセッションのみを対象に処理を行うのが手っ取り早いかもしれません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/05/11 13:17

    回答ありがとうございます。

    >コネクションでセッションを取得し、リロード時にはきちんと終了処理をした上で、最新のセッションのみを対象に処理を行う
    これができたら良いのですが、ドキュメントを読んでもよくわからず・・・

    おそらく、request.sid等を引き継げば良いのでしょうが、ご存知ないでしょうか。

    当面の間は、リダイレクトの方向で進めていきたいと思います。

    キャンセル

  • 2017/05/11 13:35

    request.sidってセッションIDを意味していますか?
    https://teratail.com/questions/13824
    上記が参考になりませんか?

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る