print 'Preall test works!'
from twisted.internet import reactor, protocol
from twisted.python import log
import sys
print 'Imports done'
class PrgShell(protocol.Protocol):
data = ''
class PrgProto(protocol.ProcessProtocol):
def __init__(self, out):
print 'Prgproto instance made'
self.transportout = out.transport
self.out = out
def outReceived(self, data):
"""Called when process sends data. We send it on to transport, however if it's 'I want input', we need to activate input."""
print 'Sub said: '+data
if data == "input":
print 'Sub wants input'
self.transportout.write("input")
sleep(0.01)
self.transport(self.out.getWrit())
else:
self.transportout.write(data)
def getWrit(self):
print 'Proto gave input to prg'
data = self.data
self.data = ''
return data
def connectionMade(self):
global reactor
print 'Connected'
proto = self.PrgProto(self)
addr = "C:\\Documents and Settings\\papa\\My Documents\\Pyt开发者_如何学Gohon\\Files\\Maze\\exe\\maze.exe"
reactor.spawnProcess(proto, addr)
print 'Procces spawned!'
def dataReceived(self, data):
print 'Data recived: '+data
self.data+=data
print 'About to do stuff'
factory = protocol.ServerFactory()
factory.protocol = PrgShell
#f = open("errors.txt", 'w')
#log.startLogging(f)
#print 'Logging started'
reactor.listenTCP(8000,factory)
print 'Runing'
reactor.run()
The program in question prints stuff first thing. When I connect to it, via raw sockets, it doesn't send anything. Here's the output:
Preall test works!
Imports done
About to do stuff
Runing (connect)
Connected
Prgproto instance made
Procces spawned!
Am I missing anything?
Thanks in advance.
Replace reactor.spawnProcess(proto, addr)
with reactor.spawnProcess(proto, addr, ['maze'], {})
.
Past experience has show that if you don't pass exe name as the first argument then nothing useful happens. However I have yet to find a reasonable explanation for why this happens.
Also you don't need global reactor
. When you import the reactor
you add it to the top level script namespace. This means that all functions and class in the same file can use it without declaring a global or importing again.
Also, you should not be using sleep(0.01)
because:
- Its not a builtin function. You need to import it from the
time
module. - Twisted is a asynchronous framework where function should avoid blocking at all costs, and
time.sleep()
(link) by its definition is a blocking call.
You should instead use reactor.callLater()
link where you provide it will a callback and a time period. This will let twisted handle other things (like a new connection) while you wait.
Finally, you code at the moment would require the user to enter input before the program asks for any. This is because getWrit
just sends stuff already in the buffer rather than asking the user. This means that if the user hasn't sent any data before getWrit
is called then it will just return an empty string.
It would be a better idea if you used a deferred. Then what you would do is call getWrit
which would immanently return a deferred and clear the data buffer. Then in dataReceived
you would append data to the buffer until you got a newline character (\n
). At which point you would call the deferred set up in getWrit
.
Something like this:
print 'Preall test works!'
from twisted.internet import reactor, protocol, defer
from twisted.python import log
import sys
print 'Imports done'
class PrgShell(protocol.Protocol):
data = ''
class PrgProto(protocol.ProcessProtocol):
def __init__(self, out):
print 'Prgproto instance made'
self.transportout = out.transport
self.out = out
def outReceived(self, data):
"""Called when process sends data. We send it on to transport, however if it's 'I want input', we need to activate input."""
print 'Sub said: '+data
if data == "input":
print 'Sub wants input'
self.transportout.write("input")
d = self.out.getWrit() # getWrit returns a deferred. We store it in d to make the code more readable
d.addCallback(self.sendInput) # Here we add self.sendInput to the callback chain.
# This way self.sendInput gets called with the user input.
else:
self.transportout.write(data)
def sendInput(self, data):
self.transport.write(data)
def getWrit(self):
print 'Proto gave input to prg'
self.deferred = defer.deferred()
self.data = ''
return self.deferred
def connectionMade(self):
print 'Connected'
proto = self.PrgProto(self)
addr = "C:\\Documents and Settings\\papa\\My Documents\\Python\\Files\\Maze\\exe\\maze.exe"
reactor.spawnProcess(proto, addr, ['maze'], {})
print 'Procces spawned!'
def dataReceived(self, data):
print 'Data recived: '+data
self.data+=data
if self.data.endswith('\n'):
if self.deferred:
# We got a newline character, and there is a deferred to call, so lets call it
d, self.deferred = self.deferred, None # This will set self.deferred to none to stop mistakes later
d.callback(self.data) # Call the deferred with data. This will send the data to sendInput above.
self.data = '' # Clear the buffer
print 'About to do stuff'
factory = protocol.ServerFactory()
factory.protocol = PrgShell
#f = open("errors.txt", 'w')
#log.startLogging(f)
#print 'Logging started'
reactor.listenTCP(8000,factory)
print 'Runing'
reactor.run()
精彩评论