我正在尝试制作一个用于发送短信的p2p应用。我这样做的方法是让服务器在应用程序运行时保持运行,并连接到其他节点的服务器以发送消息。 出于测试目的,我正在使用localhost,即与自己交谈。
所以我有以下内容:
from twisted.internet import reactor
from mylib import MessageSFactory
def send_message(message):
reactor.connectTCP("localhost", 8080, MessageCFactory(message))
reactor.listenTCP(8080, MessageSFactory())
reactor.connectTCP("localhost", 8080, MessageCFactory("this message gets received"))
reactor.run()
send_message("this message doesn't")
但问题是在send_message
似乎没有效果之后调用reactor.run
(最后一行)。
问题是我只有在用户填写邮件并发送邮件时才需要运行tcp客户端部分(connectTCP
)。所以我试着通过调用send_message
来做到这一点。那么如何修复上述代码才能使其正常工作?
从我到目前为止所读到的内容来看,使用LoopingCall
将是一种方法,但是我必须将新消息存储在客户端输入变量中,并不断检查该变量是否有新消息运行send_message
这会导致用户输入和函数回调之间的延迟,这是否是我最好的选择?
在这种情况下还有其他方法吗?或者我对扭曲的架构的一些关键部分缺乏了解?
编辑:根据要求,这里是GUI代码,它接收来自客户端的消息:
from Tkinter import *
def send_message():
print("message: %s" % (e1.get()))
master = Tk()
Label(master, text="Message").grid(row=0)
e1 = Entry(master)
e1.grid(row=0, column=1)
Button(master, text='Send', command=send_message).grid(row=3, column=1, sticky=W, pady=4)
mainloop()
由于
答案 0 :(得分:2)
关键问题是Tkinter和Twisted都以类似的方式解决类似的问题,即异步响应外部事件。事实上,Tkinter专注于 gui 事件,而Twitsted专注于网络事件,这只是重要的事情。
他们所做的具体事情是他们有一个“主循环”结构,一种你无法控制的不归路。在扭曲的情况下,通常是reactor.run()
,在tkinter中,那将是Tkinter.mainloop()
。在程序退出之前,两者都不会返回。
幸运的是,你可以将Twisted改为manage tk's event loop for you!在你的程序开始时,你应该添加:
from Tkinter import Tk
from twisted.internet import tksupport
root_window = Tk()
tksupport.install(root_window)
然后,一旦你正常创建你的gui,你应该不调用Tkinter.mainloop()
,使用:
from twisted.internet import reactor
root_window.protocol("WM_DELETE_WINDOW", reactor.stop)
reactor.run()
Tk.protocol()
的奇数位是可选的,但是当gui试图退出时,通过正常关闭反应堆将摆脱一些可怕的异常。
如果还不够,这里有一些真实的,有效的代码!首先是一个非常简单的服务器
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
class Echo(Protocol):
def dataReceived(self, data):
print 'recieved:', data
def connectionLost(self, reason):
print 'connection closed', reason
f = Factory()
f.protocol = Echo
reactor.listenTCP(8080, f)
reactor.run()
和一个有gui和网络活动的客户端:
from Tkinter import *
from twisted.internet import tksupport, reactor
master = Tk()
tksupport.install(master)
def send_message():
message = e1.get()
reactor.connectTCP("localhost", 8080, MessageCFactory(message))
print("message: %s" % (message))
Label(master, text="Message").grid(row=0)
e1 = Entry(master)
e1.grid(row=0, column=1)
Button(master, text='Send', command=send_message).grid(row=3, column=1, sticky=W, pady=4)
from twisted.internet.protocol import ClientFactory, Protocol
from twisted.internet import reactor
class MessageCProto(Protocol):
def connectionMade(self):
self.transport.write(self.factory.message)
self.transport.loseConnection()
class MessageCFactory(ClientFactory):
protocol = MessageCProto
def __init__(self, message):
self.message = message
master.protocol("WM_DELETE_WINDOW", reactor.stop)
reactor.run()