2014-12-01 10 views
7

Sto cercando di creare un thread web "keepalive" per inviare un emettitore ogni 10 secondi al browser una volta che qualcuno si collega alla pagina ma riceve un errore e non è sicuro di come aggirarlo. Qualche idea su come farlo funzionare. E come potrei uccidere questa discussione una volta che viene inviata una 'disconnessione'?RuntimeError: funzionamento esterno al contesto della richiesta

Grazie!

@socketio.on('connect', namespace='/endpoint') 
def test_connect(): 
    emit('my response', {'data': '<br>Client thinks i\'m connected'}) 

    def background_thread(): 
     """Example of how to send server generated events to clients.""" 
     count = 0 
     while True: 
      time.sleep(10) 
      count += 1 
      emit('my response', {'data': 'websocket is keeping alive'}, namespace='/endpoint') 

    global thread 
    if thread is None: 
     thread = Thread(target=background_thread) 
     thread.start() 
+0

Non che questo risponda alla domanda, ma potresti volerlo gestire dal front-end. Nel tuo callback on_connect nel browser, imposta un setInterval per emettere un "ping" ogni 10000 ms, quindi fare in modo che il backend risponda con un "pong". Ti salverà da innumerevoli ore di thread di debug e perdite di memoria. (ma come nota a margine, socket.io lo fa già per te) – Tendrid

risposta

8

hai scritto il tuo thread in background in modo che lo richiede di sapere chi è il cliente, dal momento che si sta inviando un messaggio diretto ad esso. Per questo motivo il thread in background deve avere accesso al contesto della richiesta. In Flask si può installare una copia del contesto richiesta corrente in un filo con il copy_current_request_context decoratore:

@copy_current_request_context 
def background_thread(): 
    """Example of how to send server generated events to clients.""" 
    count = 0 
    while True: 
     time.sleep(10) 
     count += 1 
     emit('my response', {'data': 'websocket is keeping alive'}, namespace='/endpoint') 

paio di note:

  • Non è necessario impostare lo spazio dei nomi quando si inviano indietro per il client, per impostazione predefinita la chiamata emit si troverà nello stesso spazio dei nomi utilizzato dal client. Lo spazio dei nomi deve essere specificato quando si trasmettono o si inviano messaggi al di fuori del contesto di una richiesta.
  • Ricorda che il tuo progetto richiederà un thread separato per ogni client che si connette. Sarebbe più efficiente avere un singolo thread in background che trasmetta a tutti i client. Vedere l'applicazione di esempio che ho sul repository GitHub per un esempio: https://github.com/miguelgrinberg/Flask-SocketIO/tree/master/example

Per interrompere il filo quando il cliente si disconnette è possibile utilizzare qualsiasi meccanismo di multi-threading per consentire al filo sapere di cui ha bisogno per uscire. Questo può essere, ad esempio, una variabile globale impostata sull'evento di disconnessione. Un'alternativa non così eccezionale, facile da implementare, è aspettare che lo emit sollevi un'eccezione quando il client se ne va e usarlo per uscire dal thread.

Problemi correlati