Python Client-Server如何处理超时

Python Client-Server how to handle timeout

我有一个 TCP 客户端-服务器,其中客户端向服务器发送 shell 命令,服务器使用所述命令的输出进行响应。某些命令(如 date 或 cd)不起作用,因为我认为它们是交互式的,而我的代码不处理它。每当我发送所述命令时,我的客户端似乎挂起并只是说发送......而我的服务器从未收到任何东西。

我想弄清楚如何在可能超时的情况下处理此问题,如果发送命令的时间超过 5 秒,客户端将导致超时或简单地处理它并打印一条消息说明命令在保持客户端连接到服务器的同时没有成功执行。

这是我的代码

客户:

import socket


# Client
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # creates TCP Socket

# local host and port
LOCAL_HOST = '127.0.0.1'

PORT = 5313
BUFFER_SIZE = 5000  # size of message

sock.settimeout(5)

# connect socket to ip and port
sock.connect((LOCAL_HOST, PORT))
print("Connected to server\n")
print("Enter quit to close connection\n")
while True:

    message = input("Please enter a command:\n")  # ask user to input message
    if message == 'quit':
        break
    if len(message) == 0:
        print("Please enter something")
        message = input("Please enter a command:\n")
    print("Sending %s" % message)
    sock.send(str.encode(message))  # send message
    command = str(sock.recv(BUFFER_SIZE), "utf-8")  # receive message

    print("received %s" % command)
print("closing connection with server")
sock.close()

服务器:

import socket
import subprocess


# Server
# Some commands do not work such as cd. Date does not work on windows because it is interactive.

# creates TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.settimeout(5)

# port and server ip(localhost)
LOCAL_HOST = ''
PORT = 5313

BUFFER_SIZE = 5000  # size of message

# test connection
print("Server starting up on %s with port number %s" % (LOCAL_HOST, PORT))
# bind socket to ip and port
sock.bind((LOCAL_HOST, PORT))
# listen to socket
sock.listen(1)

# socket will accept connection and client address

print("Waiting for connection")  # waiting for connection
connection, address = sock.accept()  # accept connection with client address
print("Connected to", address)  # connected by address
while True:

    command = connection.recv(BUFFER_SIZE)  # receive message from client

    if not command:
        break

    if len(command) > 0:

        terminal = subprocess.Popen(command[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE, stdin=subprocess.PIPE)
        output = terminal.stdout.read() + terminal.stderr.read()
        output_as_string = str(output, "utf-8")
        connection.send(str.encode("0:") + str.encode(output_as_string))
        print(output_as_string)

print("Closing Server")
sock.close()
connection.close()

有多种方法可以做到这一点,但最简单的方法可能是调用 subprocess.check_output() 方法,该方法允许您指定以秒为单位的超时值,以及 returns生成的子进程,即:

[...]

while True:
    command = connection.recv(BUFFER_SIZE)  # receive message from client
    if not command:
        break
    command = command.decode("utf-8").strip()
    if len(command) > 0:
        try:
           output_as_string = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True, timeout=5.0).decode("utf-8")
        except subprocess.TimeoutExpired:
           output_as_string = "Sub-process timed out!\r\n"

        connection.send(str.encode("0:") + str.encode(output_as_string))

[...]