Уведомления

Группа в Telegram: @pythonsu

#1 Июль 28, 2016 09:56:57

glo
Зарегистрирован: 2014-10-31
Сообщения: 2
Репутация: +  0  -
Профиль   Отправить e-mail  

Twisted двунаправленный обмен

Здравствуйте, я новичок в работе с Twisted. Появилась необходимость переписать сервер на данный фрэймворк, в первом пакете от навигационного блока приходит авторизация, от него берем номер блока и отсылаем обратно подтверждение авторизации. После чего блок присылает нам информационный пакет, в котором уже нет номера блока. Нужно, каким-то образом продолжить работу с данным подключением.

 from twisted.internet.protocol import Factory, Protocol
from twisted.internet import reactor
from textwrap import wrap
from datetime import datetime
def hack(data):
    hdata = ''
    for i in data:
        x = str('%X' % i).rjust(2, '0')
        hdata += x
    return hdata
def reverse_hex(st):
    st = wrap(st, 2)                    # разбираем строку в список по два символа
    st.reverse()                        # разворачиваем
    st = ''.join(st)                    # собираем обратно
    st = int(st, 16)                    # переводим в десятичное исчисление
    return st
def ndtp1(indata):
    parse = {}
    parse['gm_time'] = datetime.fromtimestamp(
        reverse_hex(indata[4:12])).strftime('%d-%m-%Y %H:%M:%S')
    parse['position_x'] = float(reverse_hex(indata[12:20])) / 10000000
    parse['position_y'] = float(reverse_hex(indata[20:28])) / 10000000
    parse['speed'] = reverse_hex(indata[32:34])
    return parse
class Server(Protocol):
    def connectionMade(self):
        self.transport.write(b''+self.factory.quote.encode() + b'\r\n')
    def connectionLost(self, reason):
        print('connection lost ...')
    def dataReceived(self, data):
        hdataA = hack(data)
        print('In: ' + hdataA)
        print('devID: ' + str(reverse_hex(hdataA[62:68])))
        dataA = b'7e7e0e00020001ab020000000001000000000000000000000000000000'  # наш ответ 
        self.transport.write(dataA)
        while True:
           ### Вот тут бы хотелось работать с подключением и принимать навигационные данные
class ServerFactory(Factory):
    protocol = Server
    def __init__(self, quote=None):
        self.quote = quote
reactor.listenTCP(3095, ServerFactory("quote"))
reactor.run()

Офлайн

#2 Авг. 12, 2016 13:56:25

john123
Зарегистрирован: 2013-12-22
Сообщения: 56
Репутация: +  7  -
Профиль   Отправить e-mail  

Twisted двунаправленный обмен

Похоже Вы не до конца ознакомились с практикой асинхронного программирования и фреймворком Twisted в частности.

Объект Вашего класса Server должен содержать внутри себя состояние, исходя из которого будет выбираться логика обработки пакетов.
Немного теории по теме: Автоматное программирование.

Вкратце - суть в том, чтобы хранить некую переменную состояния. Например вот так:

  
STATE_INITIAL = 1
STATE_AUTHORIZED = 2
 
class Server(Protocol):
    state = STATE_INITIAL
 
    def handleAuth(self, data):
        hdataA = hack(data)
 
        # Не забываем тут про обработку ошибок,
        # если пришел неправильный пакет
 
        print('In: ' + hdataA)
        print('devID: ' + str(reverse_hex(hdataA[62:68])))
 
        dataA = b'7e7e0e00020001ab020000000001000000000000000000000000000000'  # наш ответ 
        self.transport.write(dataA)
 
        # Считаем что авторизация прошла успешно
        self.state = STATE_AUTHORIZED
 
    def handleInfo(self, data):
        # Вот тут бы хотелось работать с подключением и принимать навигационные данные
        pass
 
    def dataReceived(self, data):
        '''
        Обрабатываем пакет в зависимости от текущего состояния соединения
        '''
        if self.state is STATE_INITIAL:
            self.handleAuth(data)
        elif self.state is STATE_AUTHORIZED:
            self.handleInfo(data)
        else:
            print('Invalid packet')
  
Работает в целом это так (условно говоря): Twisted вешает фабрику ServerFactory на указанный порт (у Вас это 3095). При создании нового соединения (подключения к серверу), вышеуказанная фабрика создает экземпляр класса Server.
То есть грубо говоря на каждое активное сетевое соединение в Вашей программе существует отдельный экземпляр класса Server, который и обрабатывает это соединение.

Метод dataReceived вызывается каждый раз, когда приходят какие-то данные в сокет.
При закрытии соединения, экземпляр класса Server уничтожается автоматически (иначе будет утечка памяти).

Отредактировано john123 (Авг. 12, 2016 14:02:25)

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version