远程执行命令
远程执行命令 : 在客户端输入一个命令,通过网络传输给服务器,服务器后端运行此命令得到结果,将结果通过网络传输返回给客户端
subprocess模块
import subprocess obj = subprocess.Popen('dir', #命令 shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE ) print(obj.stdout.read().decode('gbk')) #正确命令 print(obj.stderr.read().decode('gbk')) #错误命令 #shell :命令解释器,相当于调用cmd执行指定的命令 #stdout:正确结果丢到一个管道当中 #stderr:错了丢到另一个管道当中 #windows操作系统的默认编码是gbk
# 服务端: import socket import subprocess server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(('127.0.0.1',10086)) server.listen(5) while 1: conn, addr = server.accept() # 等待客户端连接 while 1: try: cmd = conn.recv(1024).decode('utf-8') # 最大接受的字节数 # 接受命令 obj = subprocess.Popen( cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) right_msg = obj.stdout.read() error_msg = obj.stderr.read() # 通过subprocess或者执行命令的结果 print(right_msg,error_msg) conn.send(right_msg + error_msg) # gbk 的bytes # 将结果发送给客户端 except Exception: break conn.close() server.close()
# 客户端 import socket client = socket.socket() client.connect(('127.0.0.1',10086)) while 1 : cmd = input('>>>').strip() client.send(cmd.encode('utf-8')) result = client.recv(1024) print(result.decode('gbk')) client.close()
粘包现象
粘包现象1:
客户端发送一段数据,recv时只收了一小部分,客户端下次再接收的时候还是从缓冲区拿上次遗留的数据,产生粘包
客户端 ---send()命令---> 客户端缓冲区 ---网络---> 服务端缓冲区 ---recv----> 服务端
服务端会执行客户端发送的命令,例如得到1254个字节
服务端 ---send()---> 服务端缓冲区 ---网络---> 客户端缓冲区 ---recv----> 客户端
客户端只接收1024个字节,还会剩下230个字节留在客户端缓冲区
等到下一次再次输入命令时,客户端最后接收的只有230个字节,没有本次执行命令的结果
原因:只要客户端将数据send除去,就会立马进入recv状态 会直接打印在客户端缓冲区的230个字节,而不会等到本次的命令走完整个流程
粘包现象2:
如果连续快速的发送几次少量的数据,那么服务端会一次接受完毕.
# 服务端: import socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(('127.0.0.1',10086)) server.listen(5) conn,addr = server.accept() data1 = conn.recv(1024) print(data1) data2 = conn.recv(1024) print(data2) conn.send(b'taibai') conn.close() server.close()
# 客户端: import socket client = socket.socket() client.connect(('127.0.0.1',10086)) client.send(b'hello') client.send(b'world') from_server_data = client.recv(1024) print(from_server_data) client.close()
运行结果: b'helloworld'