Python Django:与TCP服务器通信(使用twisted?)
我有一个django应用程序,需要与远程TCP服务器通信。此服务器将发送包,根据包的内容,我需要向数据库添加条目并通知应用程序的其他部分。我还需要主动向TCP服务器发送请求,例如,当用户导航到某个页面时,我希望订阅TCP服务器上的某个流。因此,双向沟通需要发挥作用 到目前为止,我使用以下解决方案: 我编写了一个定制的Django命令,可以从它开始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
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应用程序中使用扭曲。还有,还有一个。
谢谢,但不幸的是,我无法控制连接到的TCP服务器。我认为,设计应该由服务器驱动,所以您要么必须实现服务器协议,在单连接上双向工作,要么在服务器不能在一个连接上工作时使用两个连接。也许我不够具体。问题不是服务器或协议无法处理双向通信。问题是如何在Django中集成这种通信。由于twisted服务器运行在不同的进程中,并且与Django不同,它是非阻塞的,因此很难从Django视图内部发送消息。也许那会更有帮助。听起来很有趣。我一定会检查这个设置。是否也可以使用Unix套接字从Twisted到Django进行通信?或者出于某种原因,这是一个坏主意吗?您需要在套接字的另一端安装一个侦听器,这意味着您需要在Django内部旋转一个线程来侦听该套接字,因为它需要是非阻塞的。(您可以运行另一个Django命令来侦听,但使用数据调用Django URL更容易)。