我想在TCP服務器上運行可執行文件並交互地從套接字連接中獲取其輸入,並將輸出發送回客戶端,直到可執行文件終止。我是用管道試圖通過它POPEN 類子的,但它不是與可執行的互動幫助(它只是需要輸入只有一次,但我想輸入將要採取的所有時間,直到程序退出)。在Python中與服務器上的可執行文件進行交互?
想我發送「1」輸入到服務器,然後服務器必須發送對應於「1」輸入到客戶端,然後問下一個輸入和做它,直到在延續可執行退出標準輸出。
我想在TCP服務器上運行可執行文件並交互地從套接字連接中獲取其輸入,並將輸出發送回客戶端,直到可執行文件終止。我是用管道試圖通過它POPEN 類子的,但它不是與可執行的互動幫助(它只是需要輸入只有一次,但我想輸入將要採取的所有時間,直到程序退出)。在Python中與服務器上的可執行文件進行交互?
想我發送「1」輸入到服務器,然後服務器必須發送對應於「1」輸入到客戶端,然後問下一個輸入和做它,直到在延續可執行退出標準輸出。
只需提供插座作爲標準輸入,輸出和子進程的錯誤。例如:
import socket
import subprocess
listener = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listener.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
listener.bind(('0.0.0.0', 0))
listener.listen(5)
print(listener.getsockname())
try:
while True:
client, addr = listener.accept()
subprocess.Popen(['cat'], stdin=client, stdout=client, stderr=client)
client.close()
except KeyboardInterrupt:
pass
finally:
listener.close()
這可能需要符合POSIX標準的操作系統。
下面是一個實現利用circuits:
server.py:
#!/usr/bin/env python
from uuid import uuid4 as uuid
from subprocess import Popen, PIPE
from circuits import handler, Component, Debugger, Event
from circuits.io import File
from circuits.net.sockets import TCPServer
from circuits.net.events import close, write
class kill(Event):
"""kill Event"""
class Command(Component):
channel = "cmd"
def __init__(self, sock, command, channel=channel):
super(Command, self).__init__(channel=channel)
self._sock = sock
self._command = command
self._buffer = None
self._p = Popen(command, shell=True, stdin=PIPE, stdout=PIPE)
self._stdin = File(
self._p.stdin, channel="{0:s}.stdin".format(self.channel)
).register(self)
self._stdout = File(
self._p.stdout, channel="{0:s}.stdout".format(self.channel)
).register(self)
self.addHandler(
handler("eof", channel=self._stdout.channel)(self._on_stdout_eof)
)
self.addHandler(
handler("read", channel=self._stdout.channel)(self._on_stdout_read)
)
def write(self, data):
self.fire(write(data), self._stdin.channel)
def kill(self):
self._p.terminate()
self.unregister()
@staticmethod
def _on_stdout_eof(self):
self.fire(kill(), self.channel)
self.fire(close(self._sock), self.parent.channel)
@staticmethod
def _on_stdout_read(self, data):
self.fire(write(self._sock, data), "server")
class Server(Component):
channel = "server"
def init(self, bind, cmd):
self.cmd = cmd
self.clients = {}
TCPServer(bind).register(self)
def connect(self, sock, host, port):
command = Command(sock, self.cmd, channel=uuid()).register(self)
self.clients[sock] = command
def disconnect(self, sock):
command = self.clients[sock]
self.fire(kill(), command.channel)
del self.clients[sock]
def read(self, sock, data):
command = self.clients[sock]
self.fire(write(data), command.channel)
server = Server(("0.0.0.0", 8000), "python app.py")
Debugger().register(server)
server.run()
app.py:
#!/usr/bin/env python
from __future__ import print_function
import sys
def function1():
print("I am function 1!")
def function2():
print("I am function 2!")
def function3():
raise SystemExit(0)
MENU_OPTIONS = (
(1, "Function 1"),
(2, "Function 2"),
(3, "Function 3")
)
FUNCTIONS = {
1: function1,
2: function2,
3: function3
}
def main():
while True:
try:
print("Menu:")
for option, description in MENU_OPTIONS:
print("{0:d}) {1:s}".format(option, description))
print()
sys.stdout.flush()
choice = raw_input("> ")
try:
FUNCTIONS[int(choice)]()
except ValueError:
print("Invalid Input")
except (KeyboardInterrupt, EOFError):
raise SystemExit(0)
if __name__ == "__main__":
main()
有關示例會話(這個例子具有已經過全面測試):
玩得開心! :)
注:我實際上是1 [circuits]的開發人員/作者。我認爲這將是寫作的一個很好的例子。
什麼是可執行文件? –
@James它是一個顯示交互式菜單以供選擇的二進制文件。告訴我任何其他信息,你想知道它不夠? – in3o
你基本上想把這個應用程序包裝到可以連接到的服務器中?你期望在這裏使用什麼樣的客戶?遠程登錄? VT100兼容? –