2014-05-10 13 views
7

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) 
+4

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

+0

Vale la pena aggiungere una risposta completa - grazie per aver riportato la risposta! –

risposta

3

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.

+1

Sei proprio sicuro, questa è una soluzione ragionevole? Sembra che tu abbia aggiustato il cliente, cosa ha danneggiato il server. E un altro client con lo stesso problema causerà nuovamente il problema sul server e non ci sarà nulla contro client mal configurati o addirittura malintenzionati. – allo