Каков наилучший способ обработки полученных сообщений в Twisted для Python? - PullRequest
0 голосов
/ 23 апреля 2020

Я новичок в Python и ищу некоторую помощь с архитектурой. Вот мои настройки: у меня есть устаревшее клиентское приложение, написанное на LiveCode, которое работает в нескольких местах для отображения синхронизированной информации в зависимости от требований сервера. Думайте об этом как о киоске. Эта часть клиента никуда не денется.

Серверное приложение - это то, что я переписываю в Python. Моя цель состоит в том, чтобы серверное приложение работало постоянно, прислушивалось к подключению клиентских сокетов и отправляло / получало данные от этих клиентов. Я успешно передал сообщения между этим клиентским приложением LiveCode и сценарием python, который использует Twisted для обработки сокетов, поэтому теперь мне нужно начать обрабатывать эти сообщения. Код выглядит примерно так:

from twisted.internet.protocol import Factory
from twisted.protocols.basic import LineReceiver
from twisted.internet import reactor

class MessageListener(LineReceiver):

    def __init__(self, users):
        self.users = users
        self.name = None

    def connectionMade(self):
        d = self.transport.getHost()
        print("Connection established with {}:{}".format(d.host, d.port))

    def connectionLost(self, reason):
        print("Connection lost: {}".format(reason))
        if self.name in self.users:
            del self.users[self.name]

    def dataReceived(self, line):
        d = self.transport.getHost()
        print("Received message from {}:{}...{}".format(d.host, d.port, line))
        self.handle_GOTDATA(line)

    def handle_GOTDATA(self, msg):
        #convert "msg" to string and parse it into the necessary chunks

        #*****Go do something based on the requestor and the command*****
        #Use if-elif or dictionary to determine which function to run
        #based on what the string tells us.
        #Should these functions be defined here or in a separate class?

class MessageListenerFactory(Factory):

    def __init__(self):
        self.users = {} # maps user names to Chat instances

    def buildProtocol(self, addr):
        return MessageListener(self.users)

reactor.listenTCP(50010, MessageListenerFactory())

reactor.run()

Пара вопросов:

  1. Функция handle_GOTDATA () - это место, где я буду принимать полученное сообщение, анализировать его в куски, которые говорят мне, что делать с данными, а затем вызвать другую функцию в зависимости от того, что нужно сделать с этими данными. Должен ли я просто определить все 20 из этих функций в одном и том же классе «MessageListener», или я пишу отдельный класс, чтобы сохранить все эти функции? Я мог бы получить 10 сообщений примерно в одно и то же время, и им, возможно, понадобится вызвать одну и ту же функцию, поэтому я не был уверен, что лучший подход к архитектуре здесь.

  2. Я также хочу построить GUI для взаимодействия с сервером для устранения неполадок и мониторинга при необходимости. Я знаком с Tkinter, и это было бы хорошо для этого, и я могу написать GUI в отдельном файле и также подключить его к серверу через сокет. Но буду ли я использовать тот же прослушиватель сокетов, реализованный выше, и просто передавать ему похожие сообщения? Или я должен создать отдельный класс и фабрику для прослушивания соединений GUI?

1 Ответ

0 голосов
/ 23 апреля 2020

Если вы собираетесь использовать LineReceiver, вам не следует переопределять dataReceived. Вместо этого переопределите lineReceived. Если ваш протокол не ориентирован на строки, вы, вероятно, не хотите использовать LineReceiver. Также вы можете рассмотреть возможность использования интерфейса Tubes в любом случае.

Должен ли я просто определить все 20 из этих функций в этом же классе «MessageListener», или я пишу отдельный класс для хранения всех этих функций?

Вероятно, вы должны поместить их в другой класс. Если вы поместите их в MessageListener, то у вас будет больше трудностей с тестированием, рефакторингом и обслуживанием кода, потому что ваш протокол logi c тесно связан с журналом вашего приложения c.

Определите явный интерфейс MessageListener использует для отправки событий высокого уровня, представляющих сетевые действия. Затем реализуйте этот интерфейс в соответствии с вашим конкретным приложением. Позже вы можете реализовать его по-другому для другого приложения. Или вы можете написать тест двойников. Или вы можете изменить свой протокол, не меняя логи приложения c. Разделение двух частей дает вам большую гибкость по сравнению с объединением их обоих в один класс.

Я мог бы получить 10 сообщений примерно в одно и то же время, и им, возможно, потребуется вызвать одну и ту же функцию, поэтому Я не был уверен, что лучший архитектурный подход здесь.

Я думаю, что это ортогонально, но если это достаточно важная часть вашего протокола или логики приложения c, вы можете подумать о создании какого-то вида векторизации в явный интерфейс, который я упоминал выше. Вместо appObj.doOneThing(oneThing) возможно, у вас есть appObj.doSeveralThings([oneThing, anotherThing]).

Я также хочу создать GUI для взаимодействия с сервером для устранения неполадок и мониторинга при необходимости. Я знаком с Tkinter, и это было бы хорошо для этого, и я могу написать GUI в отдельном файле и также подключить его к серверу через сокет. Но буду ли я использовать тот же прослушиватель сокетов, реализованный выше, и просто передавать ему похожие сообщения? Или я должен создать отдельный класс и фабрику для прослушивания соединений GUI?

Это зависит от взаимодействий, которые вы хотите выполнить, я полагаю. Если это GUI с дополнительными привилегиями по сравнению с обычным клиентом, вам нужен протокол и сервер с функциями аутентификации и авторизации или вы не должны использовать один и тот же сервер и протокол, поскольку вы рискуете предоставить клиентам эти дополнительные привилегии.

Если вы просто хотите смоделировать реального клиента с помощью своего рода дружественного к отладке интерфейса, который позволяет вам легко взаимодействовать с сервером способами, которые клиент обычно взаимодействует с ним, но с интерфейсом, который делает это проще для вас, вы может (и предположительно должен) подключиться к тому же серверу.

...