Python Django:与TCP服务器通信(使用twisted?)

Python Django:与TCP服务器通信(使用twisted?),python,django,tcp,twisted,Python,Django,Tcp,Twisted,我有一个django应用程序,需要与远程TCP服务器通信。此服务器将发送包,根据包的内容,我需要向数据库添加条目并通知应用程序的其他部分。我还需要主动向TCP服务器发送请求,例如,当用户导航到某个页面时,我希望订阅TCP服务器上的某个流。因此,双向沟通需要发挥作用 到目前为止,我使用以下解决方案: 我编写了一个定制的Django命令,可以从它开始 python manage.py listen 此命令将使用reactor.connectTCP(IP、端口、工厂)启动twisted socket

我有一个django应用程序,需要与远程TCP服务器通信。此服务器将发送包,根据包的内容,我需要向数据库添加条目并通知应用程序的其他部分。我还需要主动向TCP服务器发送请求,例如,当用户导航到某个页面时,我希望订阅TCP服务器上的某个流。因此,双向沟通需要发挥作用

到目前为止,我使用以下解决方案:

我编写了一个定制的Django命令,可以从它开始

python manage.py listen
此命令将使用
reactor.connectTCP(IP、端口、工厂)
启动twisted socket服务器,因为它是一个django命令,所以我将可以访问数据库和应用程序的所有其他部分

但是,由于我还希望能够向TCP服务器发送由某个django视图触发的内容,因此我有一个额外的套接字服务器,它通过
reactor.listenTCP(端口,服务器工厂)
在我的twisted应用程序中启动

然后,我将在django应用程序中,在新线程中直接连接到此服务器:

class MSocket:

    def __init__(self):
        self.stopped = False
        self.socket = None
        self.queue = []
        self.process = start_new_thread(self.__connect__, ())
        atexit.register(self.terminate)


    def terminate(self):
        self.stopped = True
        try:
            self.socket.close()
        except:
            pass

    def __connect__(self):
        if self.stopped:
            return
        attempts = 0
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while True and not self.stopped:
            try:
                print "Connecting to Socket Server..."
                self.socket.connect(("127.0.0.1", settings.SOCKET_PORT))
                print "Connection Successful!"
                for msg in self.queue:
                    self.socket.send(msg)
                self.queue = []
                break
            except:
                pause = min(int(round(1.2**attempts)), 30)
                print "Connection Failed! Try again in " + str(pause) + " seconds."
                sleep(pause)
                attempts += 1

        self.__loop__()

    def __loop__(self):
        if self.stopped:
            return
        while True and not self.stopped:
            try:
                data = self.socket.recv(1024)
            except:
                try:
                    self.socket.close()
                except:
                    pass
                break
            if not data:
                break
        self.__connect__()

    def send(self, msg):
        try:
            self.socket.send(msg)
            return True
        except:
            self.queue.append(msg)
            return False


m_socket = MSocket()
然后,
m_socket
将由主
urls.py
导入,以django开头

所以我的设置看起来像这样:

正在发送到TCP服务器:

Django (connect:8001) ------->  (listen:8001) Twisted (connect:4444) ------> (listen:4444) TCP-Server
从TCP服务器接收

TCP-Server (listen:4444) ------> (connect:4444) Twisted ---(direct access)---> Django

这一切似乎都是这样,但我担心这不是一个真正好的解决方案,因为我必须打开这个额外的TCP连接。因此,我现在的问题是,设置是否可以优化(我相信它可以),以及如何进行优化。

据我现在了解,问题是如何将Twisted集成到Django应用程序中。这似乎不是一个好主意,因为Twisted的事件循环会阻止进程

您可以尝试在非阻塞环境中运行Django,并使用gevent实现所有需要的通信。 如果这是不可能的-有一个建议作为在Django中使用Twisted的方法(或者更确切地说,在Twisted中使用Django位)


就我个人而言,我会和gevent一起去。在使用Twisted大约2年后,它似乎是一个功能强大但又陈旧、沉重、难以学习且难以调试的工具。

除非您使用monkey补丁Django(如@pss所述),否则这是行不通的 我也遇到过类似的情况,所以我就是这么做的

  • 运行一个单独的扭曲执事
  • 要从Django通信到Twisted,请使用Unix套接字。本地twisted服务器可以监听Unix套接字(AF_Unix),Django只需连接到该套接字即可。这将避免通过TCP堆栈
  • 要从Twisted到Django进行通信,您有多种选择, a) 使用数据调用Django url b) 启动脚本(Django管理命令) c) 使用芹菜启动上述Django命令 d) 使用队列(zeromq或rabbit)并让您的Django管理命令侦听队列(首选)

  • 最后一个选项,您可以获得更好的吞吐量、耐用性以及它的伸缩性。

    您可能想考虑在Django应用程序中使用扭曲。还有,还有一个。

    谢谢,但不幸的是,我无法控制连接到的TCP服务器。我认为,设计应该由服务器驱动,所以您要么必须实现服务器协议,在单连接上双向工作,要么在服务器不能在一个连接上工作时使用两个连接。也许我不够具体。问题不是服务器或协议无法处理双向通信。问题是如何在Django中集成这种通信。由于twisted服务器运行在不同的进程中,并且与Django不同,它是非阻塞的,因此很难从Django视图内部发送消息。也许那会更有帮助。听起来很有趣。我一定会检查这个设置。是否也可以使用Unix套接字从Twisted到Django进行通信?或者出于某种原因,这是一个坏主意吗?您需要在套接字的另一端安装一个侦听器,这意味着您需要在Django内部旋转一个线程来侦听该套接字,因为它需要是非阻塞的。(您可以运行另一个Django命令来侦听,但使用数据调用Django URL更容易)。