Python 'socketserver' 只处理第一个请求
Python 'socketserver' only ever handles the first request
客户端输出
为了说明问题,这里是 运行 在客户端上运行时的代码。可以看出,第一个命令成功(它总是成功)并且即使在错误命令的情况下它也会成功 return stderr.
Pwny ~>df
Filesystem 1K-blocks Used Available Use% Mounted on
udev 1895788 0 1895788 0% /dev
tmpfs 386392 1416 384976 1% /run
/dev/sda1 478612200 43470808 410755756 10% /
tmpfs 1931948 78200 1853748 5% /dev/shm
tmpfs 5120 0 5120 0% /run/lock
tmpfs 386388 60 386328 1% /run/user/1000
Pwny ~>pwd
Pwny ~>pwd
[~] Connection aborted
Pwny ~>
服务器输出
这是我服务器的输出。
└─$ /bin/python3 /home/user/Desktop/tcpserver/socketserver.py
[*] Started server 0.0.0.0:9999
[*] 192.168.137.1:1051 connected
[~] 192.168.137.1:1051 df
TCP 客户端程序
这是我的客户端代码:
import socket
class TCPClient:
@staticmethod
def run(host, port, buffer_size=1024, encoding='utf-8'):
HOST = host
PORT = port
BUFFER_SIZE = buffer_size
ENCODING = encoding
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
tx: bytes = bytes(input("Pwny ~>"), ENCODING)
tx += b"\n"
if tx == b"exit":
break
else:
try:
s.sendall(tx)
full_msg: bytes = b''
while True:
msg: bytes = s.recv(BUFFER_SIZE)
if len(msg) == 0:
break
full_msg += msg
print(full_msg.decode(ENCODING))
except ConnectionAbortedError:
print("[~] Connection aborted")
except OSError:
print("[~] An OS error occurred")
if __name__ == '__main__':
tcp_client = TCPClient()
tcp_client.run(host='192.168.137.2', port=9999, buffer_size=128, encoding='utf-8')
TCP SocketServer程序
这是socketserver程序(我怀疑我在这里做某事,非常感谢帮助)
import socketserver
import subprocess
from subprocess import CompletedProcess
class ThreadingServer(socketserver.ThreadingMixIn,socketserver.TCPServer): pass
class TCPRequestHandler(socketserver.StreamRequestHandler):
def setup(self) -> None:
return super().setup()
def handle(self) -> None:
ENCODING: str = 'utf-8'
BUFFER_SIZE: int = 128
client_address: str = self.request.getpeername()[0]
client_port: int = self.request.getpeername()[1]
print(f"[*] {client_address}:{client_port} connected")
client_cmd: str = self.rfile.readline().decode(ENCODING).strip()
print(f"[~] {client_address}:{client_port} {client_cmd}")
output: CompletedProcess = subprocess.run(client_cmd,shell=True,capture_output=True)
""" Returns 0 for success and >= 1 for failure"""
if output.returncode == 0: # success
self.wfile.write(output.stdout)
else: # failure when > 0
self.wfile.write(output.stderr)
def finish(self) -> None:
return super().finish()
if __name__ == '__main__':
with ThreadingServer(('0.0.0.0',9999),TCPRequestHandler) as server:
print(f"[*] Started server {server.server_address[0]}:{server.server_address[1]}")
server.serve_forever()
您的客户端和服务器都有问题。
客户端使用套接字.recv()
读取数据,但是当服务器输出完成时,这将在第一个命令结束时永远阻塞。它会 return b''
只有在 EOF,当套接字被服务器关闭时。由于服务器问题(如下),它似乎可以工作。
您的服务器代码仅读取一行,生成命令,发送输出,然后 returns 超出 handle()
,之后连接关闭。由于这个关闭,客户端实际工作(它从 recv()
获得 b''
)。
要修复服务器,请在循环中执行 readline()
直到它 returns b''
(客户端关闭套接字)并且最好 flush()
发送后的写入流命令输出。
示例服务器处理程序:
def handle(self) -> None:
ENCODING: str = 'utf-8'
BUFFER_SIZE: int = 128
client_address: str = self.request.getpeername()[0]
client_port: int = self.request.getpeername()[1]
print(f"[*] {client_address}:{client_port} connected")
while True:
line: str = self.rfile.readline()
if line == b'':
break
client_cmd: str = line.decode(ENCODING).strip()
print(f"[~] {client_address}:{client_port} {client_cmd}")
output: CompletedProcess = subprocess.run(client_cmd,shell=True,capture_output=True)
""" Returns 0 for success and >= 1 for failure"""
if output.returncode == 0: # success
self.wfile.write(output.stdout)
else: # failure when > 0
self.wfile.write(output.stderr)
self.wfile.flush()
要修复客户端和整个设置,您可能需要实施某种框架,对于客户端命令,这当前是一个换行符(因为您使用了 readline),但对于服务器输出,您需要找出一个单独取景。
客户端输出
为了说明问题,这里是 运行 在客户端上运行时的代码。可以看出,第一个命令成功(它总是成功)并且即使在错误命令的情况下它也会成功 return stderr.
Pwny ~>df
Filesystem 1K-blocks Used Available Use% Mounted on
udev 1895788 0 1895788 0% /dev
tmpfs 386392 1416 384976 1% /run
/dev/sda1 478612200 43470808 410755756 10% /
tmpfs 1931948 78200 1853748 5% /dev/shm
tmpfs 5120 0 5120 0% /run/lock
tmpfs 386388 60 386328 1% /run/user/1000
Pwny ~>pwd
Pwny ~>pwd
[~] Connection aborted
Pwny ~>
服务器输出
这是我服务器的输出。
└─$ /bin/python3 /home/user/Desktop/tcpserver/socketserver.py
[*] Started server 0.0.0.0:9999
[*] 192.168.137.1:1051 connected
[~] 192.168.137.1:1051 df
TCP 客户端程序
这是我的客户端代码:
import socket
class TCPClient:
@staticmethod
def run(host, port, buffer_size=1024, encoding='utf-8'):
HOST = host
PORT = port
BUFFER_SIZE = buffer_size
ENCODING = encoding
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
while True:
tx: bytes = bytes(input("Pwny ~>"), ENCODING)
tx += b"\n"
if tx == b"exit":
break
else:
try:
s.sendall(tx)
full_msg: bytes = b''
while True:
msg: bytes = s.recv(BUFFER_SIZE)
if len(msg) == 0:
break
full_msg += msg
print(full_msg.decode(ENCODING))
except ConnectionAbortedError:
print("[~] Connection aborted")
except OSError:
print("[~] An OS error occurred")
if __name__ == '__main__':
tcp_client = TCPClient()
tcp_client.run(host='192.168.137.2', port=9999, buffer_size=128, encoding='utf-8')
TCP SocketServer程序
这是socketserver程序(我怀疑我在这里做某事,非常感谢帮助)
import socketserver
import subprocess
from subprocess import CompletedProcess
class ThreadingServer(socketserver.ThreadingMixIn,socketserver.TCPServer): pass
class TCPRequestHandler(socketserver.StreamRequestHandler):
def setup(self) -> None:
return super().setup()
def handle(self) -> None:
ENCODING: str = 'utf-8'
BUFFER_SIZE: int = 128
client_address: str = self.request.getpeername()[0]
client_port: int = self.request.getpeername()[1]
print(f"[*] {client_address}:{client_port} connected")
client_cmd: str = self.rfile.readline().decode(ENCODING).strip()
print(f"[~] {client_address}:{client_port} {client_cmd}")
output: CompletedProcess = subprocess.run(client_cmd,shell=True,capture_output=True)
""" Returns 0 for success and >= 1 for failure"""
if output.returncode == 0: # success
self.wfile.write(output.stdout)
else: # failure when > 0
self.wfile.write(output.stderr)
def finish(self) -> None:
return super().finish()
if __name__ == '__main__':
with ThreadingServer(('0.0.0.0',9999),TCPRequestHandler) as server:
print(f"[*] Started server {server.server_address[0]}:{server.server_address[1]}")
server.serve_forever()
您的客户端和服务器都有问题。
客户端使用套接字.recv()
读取数据,但是当服务器输出完成时,这将在第一个命令结束时永远阻塞。它会 return b''
只有在 EOF,当套接字被服务器关闭时。由于服务器问题(如下),它似乎可以工作。
您的服务器代码仅读取一行,生成命令,发送输出,然后 returns 超出 handle()
,之后连接关闭。由于这个关闭,客户端实际工作(它从 recv()
获得 b''
)。
要修复服务器,请在循环中执行 readline()
直到它 returns b''
(客户端关闭套接字)并且最好 flush()
发送后的写入流命令输出。
示例服务器处理程序:
def handle(self) -> None:
ENCODING: str = 'utf-8'
BUFFER_SIZE: int = 128
client_address: str = self.request.getpeername()[0]
client_port: int = self.request.getpeername()[1]
print(f"[*] {client_address}:{client_port} connected")
while True:
line: str = self.rfile.readline()
if line == b'':
break
client_cmd: str = line.decode(ENCODING).strip()
print(f"[~] {client_address}:{client_port} {client_cmd}")
output: CompletedProcess = subprocess.run(client_cmd,shell=True,capture_output=True)
""" Returns 0 for success and >= 1 for failure"""
if output.returncode == 0: # success
self.wfile.write(output.stdout)
else: # failure when > 0
self.wfile.write(output.stderr)
self.wfile.flush()
要修复客户端和整个设置,您可能需要实施某种框架,对于客户端命令,这当前是一个换行符(因为您使用了 readline),但对于服务器输出,您需要找出一个单独取景。