J'ai une application similaire à une écriture Chat en python qui a l'intention de faire les choses suivantes:Comment arrêter un client websocket sans arrêt réacteur
- Une invite pour l'utilisateur d'entrer l'adresse du serveur websocket.
- Créez ensuite un client Websocket qui se connecte au serveur et envoie/reçoit des messages. Désactive la possibilité de créer un client websocket.
- Après avoir reçu "fermer" du serveur (PAS un cadre proche), le client devrait abandonner la connexion et réactiver l'application pour créer un client. Revenez à 1.
- Si l'utilisateur quitte l'application, il quitte le client websocket s'il y en a un en cours d'exécution.
Mon approche pour cela consiste à utiliser un thread principal pour gérer les entrées utilisateur. Lorsque l'utilisateur clique, un thread est créé pour WebSocketClient en utilisant le module torsadé d'AutoBahn et lui transmet une file d'attente. Vérifiez si le réacteur fonctionne ou non et démarrez-le si ce n'est pas le cas. Écrasement sur la méthode de message pour mettre un drapeau de fermeture dans la file d'attente lors de la fermeture. Le thread principal sera occupé à vérifier la file d'attente jusqu'à la réception du drapeau et retournera au début. Le code ressemble à suivre.
Fil principal.
def main_thread():
while True:
text = raw_input("Input server url or exit")
if text == "exit":
if myreactor:
myreactor.stop()
break
msgq = Queue.Queue()
threading.Thread(target=wsthread, args=(text, msgq)).start()
is_close = False
while True:
if msgq.empty() is False:
msg = msgq.get()
if msg == "close":
is_close = True
else:
print msg
if is_close:
break
print 'Websocket client closed!'
Usine et protocole.
class MyProtocol(WebSocketClientProtocol):
def onMessage(self, payload, isBinary):
msg = payload.decode('utf-8')
self.Factory.q.put(msg)
if msg == 'close':
self.dropConnection(abort=True)
class WebSocketClientFactoryWithQ(WebSocketClientFactory):
def __init__(self, *args, **kwargs):
self.queue = kwargs.pop('queue', None)
WebSocketClientFactory.__init__(self, *args, **kwargs)
Processus client.
def wsthread(url, q):
factory = WebSocketClientFactoryWithQ(url=url, queue=q)
factory.protocol = MyProtocol
connectWS(Factory)
if myreactor is None:
myreactor = reactor
reactor.run()
print 'Done'
Maintenant, j'ai un problème. Il semble que mon thread client ne s'arrête jamais. Même si je reçois "close", il semble toujours en cours d'exécution et chaque fois que j'essaie de recréer un nouveau client, cela crée un nouveau thread. Je comprends que le premier thread ne s'arrêtera pas puisque reactor.run()
fonctionnera pour toujours, mais à partir du 2ème thread et sur, il devrait être non-bloquant puisque je ne le lance plus. Comment puis-je changer cela?
EDIT:
Je finis par le résoudre avec
- Ajout
stopFactory()
après la déconnexion. - Effectuez des fonctions de protocole avec
reactor.callFromThread()
. - Démarrez le réacteur dans le premier thread et placez les clients dans d'autres threads et utilisez
reactor.callInThread()
pour les créer.
Le serveur peut fermer la socket client, souhaitez-vous gérer toutes les erreurs client sur le serveur? – dsgdfg
@dsgdfg Le fait est que j'essaie de dupliquer une application existante, mais je ne possède pas le client ou le serveur, donc je n'ai pas le code. De ce que je sais en utilisant wireshark, je peux voir le serveur envoie le message "fermer" et le client répond un cadre proche avec le code 1001 et quitte juste. Je veux faire la même chose mais je ne sais pas comment fermer le client et laisser le fil revenir afin que je puisse faire d'autres travaux. – vance46