开发者

What's wrong with my twisted server that's supposed to take a .exe and send its stdio to anyone who asks. Instead, it doesn't send anything

开发者 https://www.devze.com 2023-03-01 21:43 出处:网络
print \'Preall test works!\' from twisted.internet import reactor, protocol from twisted.python import log
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:

  1. Its not a builtin function. You need to import it from the time module.
  2. 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()
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号