Что не так с моим скрученным сервером, который должен принимать .exe и отправлять его stdio всем, кто спрашивает. Вместо этого он ничего не отправляет - PullRequest
5 голосов
/ 30 апреля 2011
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\\Python\\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()

Программа, о которой идет речь, печатает материал первым делом. Когда я подключаюсь к нему через необработанные сокеты, он ничего не отправляет. Вот вывод:

Preall test works!
Imports done
About to do stuff
Runing (connect)
Connected
Prgproto instance made
Procces spawned!

Я что-то упустил?

Заранее спасибо.

1 Ответ

1 голос
/ 09 мая 2011

Замените reactor.spawnProcess(proto, addr) на reactor.spawnProcess(proto, addr, ['maze'], {}).

Опыт прошлых лет показал, что если вы не передадите exe-имя в качестве первого аргумента, тогда ничего полезного не произойдет.Однако мне еще предстоит найти разумное объяснение, почему это происходит.

Также вам не нужно global reactor.При импорте reactor вы добавляете его в пространство имен скрипта верхнего уровня.Это означает, что все функции и классы в одном и том же файле могут использовать его без объявления глобального или повторного импорта.

Кроме того, вам не следует использовать sleep(0.01), поскольку:

  1. Егоне встроенная функция.Вам необходимо импортировать его из модуля time .
  2. Twisted - это асинхронная структура, в которой функция должна избегать блокировок любой ценой, и time.sleep() ( ссылка )) по определению является блокирующим вызовом.

Вместо этого следует использовать reactor.callLater() ссылку , где вы предоставляете это обратный вызов и период времени.Это позволит витой обрабатывать другие вещи (например, новое соединение), пока вы ждете.

Наконец, ваш код на данный момент потребует от пользователя ввода ввода, прежде чем программа запросит какой-либо.Это потому, что getWrit просто отправляет материал, уже находящийся в буфере, а не спрашивает пользователя.Это означает, что если пользователь не отправил никаких данных до вызова getWrit, он просто вернет пустую строку.

Было бы лучше, если бы вы использовали отложенный метод.Затем вы должны вызвать getWrit, который бы немедленно возвратил отложенный и очистил буфер данных.Затем в dataReceived вы добавляете данные в буфер, пока не получите символ новой строки (\n).В этот момент вы бы назвали отложенный набор в getWrit.

Примерно так:

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()
...