Sto provando a creare un server Flask che trasmette i dati al client utilizzando sse. Il pezzo di codice di prova qui sotto sembra fare il trucco, ma mi sono imbattuto in un problema relativo alla gestione dei disconnect dei client.Flask sse-stream non terminato dopo il disinserimento di firefox
Quando si utilizza Firefox come client (versioni 28 o 29), i dati iniziano lo streaming come previsto. Tuttavia, quando ricarico la pagina, viene aperto un nuovo flusso (come previsto) ma il vecchio flusso rimane ancora. Il thread eventgen() che gestisce lo stream non viene mai terminato. Su altri client (ho provato IE usando l'implementazione di Polyfill EventSource di Yaffle e Chrome), ricaricando o chiudendo i risultati della pagina in una disconnessione del client, che si traduce in un errore del socket lato server 10053 (client disconnesso dall'host). Questo termina il ciclo e mantiene solo i flussi attivi vivi, che è il comportamento previsto.
Utilizzando Process Explorer, ho notato che la connessione TCP sul lato client (Firefox) si blocca nello stato FIN_WAIT2, mentre la connessione sul lato server si blocca nello stato CLOSE_WAIT. La cosa strana è che su 1 delle 3 macchine (tutte Win 7 x64) che eseguono Firefox l'ho provato, le disconnessioni sono state gestite correttamente. L'esecuzione su Python 2.6.5 e 2.7.6 ha prodotto gli stessi risultati.
Ho anche provato a sostituire il server Flask incorporato con il gevent WSGIserver basato su greenlet, ma ciò comporta esattamente lo stesso comportamento. Inoltre, dovrebbe essere utilizzata una qualche forma di threading/eventlet poiché altrimenti il ciclo eventgen() blocca il server.
Il codice di prova riportato di seguito serve la pagina definita in make_html() durante la navigazione su localhost: 5000 e apre un flusso su/stream. Lo stream mostra i massaggi del modulo {"content": 0.5556278827744346, "local_id": 4, "msg": 6}, dove id_locale è l'id del flusso aperto e msg è il numero del messaggio corrente in questo flusso.
import time, random
import flask
from flask import Flask, json
def make_html():
return """
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script type=text/javascript>
var source = new EventSource('/stream');
source.onmessage = function (event) {
var data = event.data;
var logdiv = $('#log');
logdiv.empty();
logdiv.append('<div class="event">' + data + '</div>');
};
</script>
<h1>Log</h1>
<div id=log>Log ...</div>
<hr />
"""
# ---- Flask app ----
app = Flask(__name__)
@app.route('/')
def index():
return make_html()
counter = 0
def eventgen():
global counter
counter += 1
local_id = counter
msg_count = 0
while True:
msg_count += 1
data = {'msg': msg_count, 'content': random.random(), 'local_id': local_id}
data = json.dumps(data)
yield 'data: ' + data + '\n\n'
print local_id, ':', data
time.sleep(0.5)
@app.route('/stream')
def eventstream():
return flask.Response(eventgen(), mimetype="text/event-stream")
if __name__ == '__main__':
app.run(threaded=True)
Mi sembra di aver trovato la fonte di questo problema. Il problema sembra essere con lo scanner di collegamento di surf-shield di AVG e Firefox. Disabilitare il surf-shield sembra risolvere il problema. Il PC su cui già funzionava stava eseguendo Avast al posto di AVG. Sto indovinando che questo è un bug in AVG, che probabilmente dovrebbe essere risolto. – mojoritty
Vale la pena aggiungere una risposta completa - grazie per aver riportato la risposta! –