运行reactor.run()后启动TCP客户端

mur*_*mur 6 python twisted

我正在尝试制作一个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")
Run Code Online (Sandbox Code Playgroud)

然而问题是send_messagereactor.run看起来没有效果之后调用(最后一行).

问题是我只需要connectTCP在用户填写消息时运行tcp客户端part()并发送它.所以我试着通过电话来做到这一点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()
Run Code Online (Sandbox Code Playgroud)

谢谢

Sin*_*ion 2

关键问题是 Tkinter 和 Twisted 都以类似的方式解决类似的问题,即对外部事件做出异步反应。Tkinter 专注于GUI事件而 Twitsted 专注于网络事件这一事实只是暂时的重要性。

他们所做的具体事情是他们有一个“主循环”结构,这是一种你失去控制的不归路。对于twisted,通常是reactor.run(),而在 tkinter 中,通常是Tkinter.mainloop()。在程序退出之前两者都不会返回。

幸运的是,您可以让 Twisted为您管理 tk 的事件循环! 在程序的开头,您应该添加:

from Tkinter import Tk
from twisted.internet import tksupport
root_window = Tk()
tksupport.install(root_window)
Run Code Online (Sandbox Code Playgroud)

然后,一旦你正常创建了你的 gui,你应该调用Tkinter.mainloop(),使用:

from twisted.internet import reactor
root_window.protocol("WM_DELETE_WINDOW", reactor.stop)
reactor.run()
Run Code Online (Sandbox Code Playgroud)

奇怪的一点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()
Run Code Online (Sandbox Code Playgroud)

和一个客户端,具有 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()
Run Code Online (Sandbox Code Playgroud)