我希望从客户端收到消息,并通过单独的独立流程向他们发送消息。我尝试过的代码使用了扭曲的线程方法。我试图在另一个线程上运行方法sendMessage以继续从客户端接收消息,但它等待用户键入文本。如何在不同的线程中运行sendMessage方法,以便程序继续接收客户端的数据,即使服务器端没有提供消息? 我的代码:
from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor
import time
class MultiEcho(Protocol):
def __init__(self, factory):
self.factory = factory
def connectionMade(self):
self.factory.echoers.append(self)
def dataReceived(self, data):
print 'Client Said: ' + data
reactor.callFromThread(self.sendMessage)
def connectionLost(self, reason):
self.factory.echoers.remove(self)
def sendMessage(self):
app = raw_input('Send Message to client :')
for echoer in self.factory.echoers:
echoer.transport.write(app)
class MultiEchoFactory(Factory):
def __init__(self):
self.echoers = []
def buildProtocol(self, addr):
return MultiEcho(self)
reactor.listenTCP(8000, MultiEchoFactory())
reactor.run()
答案 0 :(得分:2)
你不应该在Twisted中使用raw_input
。它阻止了主线程。您无法从其他线程调用transport.write
,因为必须从Twisted线程调用所有使用Twisted执行I / O的方法。
看起来你在这里要做的就是编写一个命令行程序,该程序采用标准输入(带行编辑)并将其发送到所有当前连接的客户端,并从中获取所有输入那些客户端并将其发送到控制台。希望以下示例显示如何使用Twisted自己的API来完成类似的事情。
from twisted.python.failure import Failure
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory
from twisted.conch.recvline import HistoricRecvLine
from twisted.conch.stdio import runWithProtocol
class ConsolePrompter(HistoricRecvLine, object):
ps = ["Message: "]
def __init__(self, multiEcho):
self.multiEcho = multiEcho
def lineReceived(self, line):
try:
if not line:
reactor.stop()
self.drawInputLine()
self.multiEcho.tellAllClients(line)
except:
f = Failure()
data = f.getTraceback()
self.terminal.write(data)
def clientSaid(self, data):
self.terminal.write("\r")
self.terminal.eraseLine()
self.terminal.write("Client Said:" + repr(data))
self.terminal.write("\n")
self.drawInputLine()
class MultiEcho(Protocol):
def __init__(self, factory):
self.factory = factory
def connectionMade(self):
self.factory.echoers.append(self)
def dataReceived(self, data):
self.factory.prompter.clientSaid(data)
def connectionLost(self, reason):
self.factory.echoers.remove(self)
class MultiEchoFactory(Factory):
def __init__(self):
self.echoers = []
self.prompter = ConsolePrompter(self)
def buildProtocol(self, addr):
return MultiEcho(self)
def tellAllClients(self, message):
for echoer in self.echoers:
echoer.transport.write(message + "\r\n")
mef = MultiEchoFactory()
reactor.listenTCP(8000, mef)
runWithProtocol(lambda: mef.prompter)