Приложение twistd (.tac) с TCPServer не работает, в то время как обычный Twisted .py работает с listenTCP

В настоящее время я пытаюсь преобразовать приложение, основанное на Twisted, в Twistd Twisted Application Framework (TAC).

Приложение работает, если я запускаю.py, но не с демоном "twistd -noy zmq2tcp.tac". Соединения ZMQ кажутся правильно открытыми, но при запуске с файлом TAC он не прослушивает порт 2323.

Пожалуйста, объясните мне причину, по которой в данном случае работает listenTCP, а не интернет.TCPServer

Файл zmq2tcp.tac:

#!/usr/bin/python
# **- encoding: utf-8 -**
from twisted.application import internet, service
from twisted.application.service import Application

from txzmq import ZmqFactory, ZmqEndpoint, ZmqSubConnection, ZmqPushConnection

from zmq2tcp import *

LISTEN_PORT = 2323

class ListenService(service.Service):
    def __init__(self):
        self.zf = ZmqFactory()
        self.minidoFactory = MinidoServerFactory()

    def startService(self):
        self.sube = ZmqEndpoint('connect', 'tcp://localhost:5557')
        self.push = ZmqEndpoint('connect', 'tcp://localhost:5558')
        self.subconn = ZmqSubConnection(self.zf, self.sube)
        self.subconn.subscribe('')

        # Create the resource
        self.minidoFactory.pushconn = ZmqPushConnection(self.zf, self.push)
        self.subconn.gotMessage = self.minidoFactory.send2tcp
        return internet.TCPServer(LISTEN_PORT, self.minidoFactory)

    def stopService(self):
        del self.sube
        del self.push
        del self.subconn

application = Application('ZMQ2TCP')
service = ListenService()
service.setServiceParent(application)

Файл zmq2tcp.py:

#!/usr/bin/env python
# **- encoding: utf-8 -**
"""
    Minido-Unleashed is a set of programs to control a home automation
    system based on minido from AnB S.A.

    Please check http://kenai.com/projects/minido-unleashed/

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

    ***

    This program connects to a STOMP server, and allow dual way communication
    with the minido bus, checking the validity of the packet before sending.
"""

###############################################################################
from __future__ import print_function
from twisted.application import internet, service
from twisted.internet.protocol import Protocol, ReconnectingClientFactory
from twisted.internet.protocol import Factory


# Other imports
import datetime
import time
import sys
import msgpack

# minido
from protocol import *

# txZMQ
from txzmq import ZmqFactory, ZmqEndpoint, ZmqPubConnection, ZmqSubConnection, ZmqPushConnection

MINIDO_LISTEN_PORT = 2323 

class MinidoServerFactory(Factory):
    def __init__(self):   
        self.connections = []

    def startedConnecting(self, connector):
        print('Started to connect.')

    def buildProtocol(self, addr):
        return MinidoProtocol(self)

    def clientConnectionLost(self, connector, reason):
        print('Lost connection.  Reason:', reason)
        ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

    def clientConnectionFailed(self, connector, reason):
        print('Connection failed. Reason:', reason)
        ReconnectingClientFactory.clientConnectionFailed(self, connector,
                                                         reason)
    def recv_message(self, message):
        print(': TCP to STOMP : %s' % (' '.join(map(lambda i: '{0:02X}'.format(i),message))))
        pushconn.push(msgpack.packb(message))

    def send2tcp(self, rawmessage, tag):
        message = msgpack.unpackb(rawmessage)
        if type(message) is tuple:
            print(": STOMP to %i TCP client(s) : %s" % (
                len(self.connections),
                ' '.join(map(lambda i: '{0:02X}'.format(i),message))))
            for conn in self.connections:
                conn.send_data(message)

if __name__ == '__main__':
    from twisted.internet import reactor
    zf = ZmqFactory()
    minidoFactory = MinidoServerFactory()
    sube = ZmqEndpoint('connect', 'tcp://localhost:5557')
    subconn = ZmqSubConnection(zf, sube)
    subconn.subscribe('') 

    subconn.gotMessage = minidoFactory.send2tcp

    push = ZmqEndpoint('connect', 'tcp://localhost:5558')
    minidoFactory.pushconn = ZmqPushConnection(zf, push)
    reactor.listenTCP(MINIDO_LISTEN_PORT, minidoFactory)
    reactor.run()

2 ответа

Решение

Проблема в том, что в вашем ListenService.startService вы создаете и возвращаете TCPServer служба, но вы не запускаете эту службу.

IService.startService не возвращает значение, поэтому вместо return internet.TCPServer(LISTEN_PORT, self.minidoFactory), делать internet.TCPServer(LISTEN_PORT, self.minidoFactory).startService(),

Это имеет очевидную проблему, которая заключается в том, что ваш stopService потом не вспомнишь где что TCPServer это остановить это позже. Было бы лучше учесть это, чтобы создать TCPServer как можно скорее и запустите / остановите его вместе с вашим сервисом, например так:

class ListenService(service.Service):
    def __init__(self):
        self.zf = ZmqFactory()
        self.minidoFactory = MinidoServerFactory()
        self.tcpService = internet.TCPServer(LISTEN_PORT, self.minidoFactory)

    def startService(self):
        self.sube = ZmqEndpoint('connect', 'tcp://localhost:5557')
        self.push = ZmqEndpoint('connect', 'tcp://localhost:5558')
        self.subconn = ZmqSubConnection(self.zf, self.sube)
        self.subconn.subscribe('')

        # Create the resource
        self.minidoFactory.pushconn = ZmqPushConnection(self.zf, self.push)
        self.subconn.gotMessage = self.minidoFactory.send2tcp
        self.tcpService.startService()

    def stopService(self):
        del self.sube
        del self.push
        del self.subconn
        return self.tcpService.stopService()

Во-первых, большое спасибо за этот прекрасный ответ. Ниже я нашел обходной путь, который тоже работает. Но я не совсем понимаю приведенное ниже решение и предпочитаю ваше решение и объяснение, поэтому я отмечу его как ОДИН.

#!/usr/bin/python
# **- encoding: utf-8 -**
from twisted.application import internet, service
from twisted.application.service import Application
from twisted.internet import reactor

from txzmq import ZmqFactory, ZmqEndpoint, ZmqSubConnection, ZmqPushConnection

from zmq2tcp import *

LISTEN_PORT = 2323

class ListenService(service.Service):
    def __init__(self):
        self.zf = ZmqFactory()
        self.minidoFactory = MinidoServerFactory()

    def startService(self):
        self.sube = ZmqEndpoint('connect', 'tcp://localhost:5557')
        self.push = ZmqEndpoint('connect', 'tcp://localhost:5558')
        self.subconn = ZmqSubConnection(self.zf, self.sube)
        self.subconn.subscribe('')

        # Create the resource
        self.minidoFactory.pushconn = ZmqPushConnection(self.zf, self.push)
        self.subconn.gotMessage = self.minidoFactory.send2tcp
        self._port = reactor.listenTCP(LISTEN_PORT, self.minidoFactory)

    def stopService(self):
        del self.sube
        del self.push
        del self.subconn

application = Application('ZMQ2TCP')
service = ListenService()
service.setServiceParent(application)
Другие вопросы по тегам