2016-01-03 2 views
15

Je suis dans la situation où je reçois un message du client. Dans la fonction qui gère cette requête (@ socketio.on), je veux appeler une fonction où un gros travail est fait. Cela ne devrait pas conduire à bloquer le thread principal et le client est censé être informé une fois le travail terminé. Ainsi je commence un nouveau fil.Python - Flask-SocketIO envoyer un message du fil: ne fonctionne pas toujours

Maintenant, je rencontre un comportement vraiment étrange: Le message n'atteint jamais le client. Cependant, le code atteint cet endroit particulier où le message est envoyé. Encore plus surprenant est le fait que s'il n'y a rien qui se passe dans le thread, sauf pour le message envoyé au client, alors la réponse trouve effectivement son chemin vers le client. Pour résumer: En résumé, si quelque chose d'intensif en calcul se produit avant l'envoi du message, il n'est pas remis, sinon il l'est.

Comme il est dit here et here, envoyer des messages à partir d'un fil aux clients ne sont pas un problème du tout:

Dans tous les exemples montré jusqu'à ce point, le serveur répond à un événement envoyé par le client. Mais pour certaines applications, le serveur doit être l'auteur d'un message. Cela peut être utile pour envoyer des notifications aux clients d'événements provenant du serveur, par exemple dans un thread d'arrière-plan.

Voici un exemple de code. Lors de la suppression des objets Sharps (#), le message ('foo from thread') ne trouve pas son chemin vers le client, sinon il le fait.

from flask import Flask 
from flask.ext.socketio import SocketIO, emit 
app = Flask(__name__) 
socketio = SocketIO(app) 

from threading import Thread 
import time 

@socketio.on('client command') 
def response(data): 
    thread = Thread(target = testThreadFunction) 
    thread.daemon = True 
    thread.start() 

    emit('client response', ['foo']) 

def testThreadFunction(): 
# time.sleep(1) 

    socketio.emit('client response', ['foo from thread']) 

socketio.run(app) 

J'utilise Python 3.4.3, Flask 0.10.1, flacon-socketio1.2, eventlet 0.17.4.

Cet exemple peut être copié et collé dans un fichier .py et le comportement peut être reproduit instantanément. Quelqu'un peut-il expliquer cet étrange comportement?

Mise à jour

Il semble y avoir un bug de eventlet. Si oui:

socketio = SocketIO(app, async_mode='threading') 

Il force l'application à ne pas utiliser l'événement même s'il est installé.

Cependant, ce n'est pas une solution applicable pour moi en utilisant 'threading' car async_mode refuse d'accepter les données binaires. Chaque fois que j'envoie des données binaires du client vers le serveur, il dit:

WebSocket transport not available. Install eventlet or gevent and gevent-websocket for improved performance.

La troisième option, en utilisant gevent comme async_mode ne fonctionne pas pour moi aussi bien que gevent ne prend pas en charge pour python 3 encore.

Alors, d'autres suggestions?

+0

@rfkortekaas COMMEnT qui ont du sens dans un protocole asynchrone? Et à part ça, la réponse est envoyée. C'est ce que "émet". L'autre chose se passe dans un fil séparé. – Schnodderbalken

+0

J'ai supprimé mon commentaire car j'ai mal interprété la question. – rfkortekaas

+0

Je me suis heurté à un problème très similaire, mais nous ne faisions rien de coûteux en informatique. Il semble être un problème avec l'acquisition du "socketio" approprié lors de l'appel de socketio.emit. Parce que l'émission a lieu, mais aucun client ne reçoit le message. L'ajout de async_mode = 'threading' semblait résoudre le problème. Mais j'espère qu'il y a un meilleur moyen – AMB0027

Répondre