2017-05-25 4 views
0

J'essaie actuellement de créer une petite démo où je connecte une socket web entre mon ordinateur et mon hôte local ws://localhost:8080/ws. Je veux que le socket Web surveille un fichier sur mon ordinateur pour les changements. S'il y a des changements, envoyez un message. La connexion et la sortie sont surveillées à l'aide d'Advanced Rest Client.Comment envoyer un message lorsque des modifications de fichiers ont été détectées? Twisted et Web Sockets

Existe-t-il une méthode spécifique que je peux utiliser sur la classe pour vérifier en permanence le contenu de ce fichier?

EDIT

J'ai mis en place un observateur en utilisant watchdog qui détecte tous les cas pour les fichiers dans un répertoire spécifié. Toutefois, mon message n'est pas envoyé dans la méthode sendFSEvent et j'ai également réalisé que mon client n'est pas enregistré lorsque je me connecte à la prise Web.

Voici mon code dans server.py

import sys 
import os 

from watchdog.observers import Observer 
from twisted.web.static import File 
from twisted.python import log 
from twisted.web.server import Site 
from twisted.internet import reactor, defer 

from autobahn.twisted.websocket import WebSocketServerFactory, \ 
    WebSocketServerProtocol, listenWS 

from MessangerEventHandler import MessangerEventHandler 


class WsProtocol(WebSocketServerProtocol): 
    def connectionMade(self): 
     print("Connection made") 
     WebSocketServerProtocol.connectionMade(self) 

    def onOpen(self): 
     WebSocketServerProtocol.onOpen(self) 
     print("WebSocket connection open") 

    def onMessage(self, payload, isBinary): 
     print("Message was: {}".format(payload)) 
     self.sendMessage("message received") 

    def sendFSEvent(self, json): 
     WebSocketProtocol.sendMessage(self, json) 
     print('Sent FS event') 

    def onClose(self, wasClean, code, reason): 
     print("Connection closed: {}".format(reason)) 
     WebSocketServerProtocol.onClose(self, wasClean, code, reason) 


class WsServerFactory(WebSocketServerFactory): 
    protocol = WsProtocol 

    def __init__(self, url='ws://localhost', port=8080): 
     addr = url + ':' + str(port) 
     print("Listening on: {}".format(addr)) 
     WebSocketServerFactory.__init__(self, addr) 
     self.clients = [] 

    def register(self, client): 
     if not client in self.clients: 
      print("Registered client: {}".format(client)) 
      self.clients.append(client) 

    def unregister(self, client): 
     if client in self.clients: 
      print("Unregistered client: {}".format(client)) 
      self.clients.remove(client) 
     self._printConnected() 

    def _printConnected(self): 
     print("Connected clients:[") 

    def notify_clients(self, message): 
     print("Broadcasting: {}".format(message)) 
     for c in self.clients: 
      c.sendFSEvent(message) 
     print("\nSent messages") 


if __name__ == '__main__': 
    if len(sys.argv) < 2: 
     print("Usage: python server_defer.py <dirs>") 
     sys.exit(1) 

    log.startLogging(sys.stdout) 

    ffactory = WsServerFactory("ws://localhost", 8080) 
    ffactory.protocol = WsProtocol 
    listenWS(ffactory) 

    observers = [] 
    for arg in sys.argv[1:]: 
     dir_path = os.path.abspath(arg) 
     if not os.path.exists(dir_path): 
      print('{} does not exist.'.format(dir_path)) 
      sys.exit(1) 
     if not os.path.isdir(dir_path): 
      print('{} is not a directory.'.format(dir_path)) 
      sys.exit(1) 

     # Check for and handle events 
     event_handler = MessangerEventHandler(ffactory, reactor, os.getcwd()) 

     observer = Observer() 
     observer.schedule(event_handler, path=dir_path, recursive=True) 
     observer.start() 

     observers.append(observer) 

    try: 
     reactor.run() 
    except KeyboardInterrupt: 
     for obs in observers: 
      obs.stop() 
     reactor.stop() 
     print("\nGoodbye") 
     sys.exit(1) 

Toute aide serait grandement appréciée.

Merci,

Brian

+0

Dans quel système d'exploitation exécuterez-vous cette application? –

+0

Windows en ce moment, mais passera à Linux (Red Hat). – Brian

+0

En * nix, il y a l'attribut 'mtime' d'un fichier (cf' os.path.getmtime (path) ') que vous pouvez vérifier périodiquement. Une autre option consiste à calculer une somme de contrôle pour le fichier et à agir lorsqu'il est modifié. – boardrider

Répondre

1

La plupart des distros d'entreprise viennent avec inotify qui est vraiment bien adapté pour le suivi des fichiers et des répertoires. L'idée de base est de capturer une liste de clients socket Web connectés lors de leur connexion. Créez ensuite un rappel qui s'exécutera lorsqu'un changement se produit sur les fichiers que vous surveillez. Dans ce rappel, vous pouvez répéter les clients et leur envoyer un message comme 'file: "blah/blah.txt" has changed'. C'est un peu foutu, mais l'extrait de code devrait clarifier les choses pour vous.

from functools import partial 
from twisted.internet import inotify 
from twisted.python import filepath 
# the rest of your imports ... 


class SomeServerProtocol(WebSocketServerProtocol): 
    def onConnect(self, request): 
     self.factory.append(self)  # <== append this client to the list in the factory 


def notification_callback(ignored, filepath, mask, ws_clients): 
    """ 
    function that will execute when files are modified 
    """ 
    payload = "event on {0}".format(filepath) 
    for client in ws_clients: 
     client.sendMessage(
      payload.encode('utf8'), # <== don't forget to encode the str to bytes before sending! 
      isBinary = False) 

if __name__ == '__main__': 
    root = File(".") 
    factory = WebSocketServerFactory(u"ws://127.0.01:8080") 
    factory.protocol = SomeServerProtocol 
    factory.clients = []  # <== create a container for the clients that connect 

    # inotify stuff 
    notify = partial(notification_callback, ws_clients=factory.clients) # <== use functools.partial to pass extra params 
    notifier = inotify.INotify() 
    notifier.startReading() 
    notifier.watch(filepath.FilePath("/some/directory"), callbacks=[notify]) 

    # the rest of your code ... 
+0

Merci! J'obtiens un 'INotifyError: Impossible d'ajouter la surveillance sur ''/home/bweber/pub_sub_example/test_files ''. Mon code est écrit comme 'notifier.watch (filepath.FilePath (" test_files "), callbacks = [notifier]). Une idée sur pourquoi je reçois cette erreur? – Brian

+0

Peu importe. Je viens de réaliser que ce dossier est sur ma machine Windows et je suis passé à Linux maintenant. Oh mon... – Brian