检测到文件更改时如何发送消息?扭曲和Web套接字

时间:2017-05-25 01:46:38

标签: python windows web-services sockets twisted

我目前正在尝试创建一个小型演示,我在计算机和本地主机ws://localhost:8080/ws之间连接一个Web套接字。我希望Web套接字监视计算机上的文件以进行更改。如果有更改,请发送消息。使用Advanced Rest Client监视连接和输出。

我是否可以在课堂上使用特定的方法来不断检查此文件的内容?

修改

我使用watchdog实现了一个观察者,它可以检测指定目录中文件的任何事件。但是,我的消息没有以sendFSEvent方式发送,我也意识到当我连接到网络套接字时,我的客户端没有被注册。

以下是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)

非常感谢任何帮助。

谢谢,

布赖恩

1 个答案:

答案 0 :(得分:1)

大多数企业发行版附带inotify,非常适合监控文件和目录。基本思想是在连接时捕获连接的Web套接字客户端列表。然后创建一个回调,该回调将在您正在监控的文件发生更改时执行。在此回调中,您可以迭代客户端并向其发送'file: "blah/blah.txt" has changed'之类的消息。它有点不稳定,但代码片段应该为你清理。

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 ...