Python 远程执行命令(Socket)
一、远程执行命令
1.服务器端:
1 import subprocess 2 import socket 3 sk=socket.socket() 4 address=('127.0.0.1',8080) 5 sk.bind(address) 6 sk.listen(3) 7 while True: 8 conn,add=sk.accept() 9 print(conn,add) 10 while True: 11 try: 12 data=conn.recv(1024) 13 except Exception: 14 break 15 16 print('%s'%(str(data,'utf8'))) 17 if not data: 18 conn.close() 19 conn,add=sk.accept() 20 print(add) 21 continue 22 # inp=input('>>>') 23 a=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE) 24 cmd_shell=a.stdout.read() 25 conn.send(cmd_shell) 26 sk.close()
解析:使用subprocess模块可以远程执行shell命令,但是会启动另外一个进程不与主进程同步,使用stdout=subprocess.PIPE参数可以使其返回主进程
a.stdout.read()返回值就是bytes类型,可以直接发送,不用做类型转换
2.客户端:
1 import socket 2 sk=socket.socket() 3 address=('127.0.0.1',8080) 4 sk.connect(address) 5 while True: 6 inp=input('>>>') 7 if inp=='exit': 8 break 9 sk.send(bytes(inp,'utf8')) 10 data=sk.recv(1024) 11 # print('%s'%(str(data,'utf8'))) 12 print(str(data,'gbk')) 13 sk.close()
当客户端接收到服务器端返回的值时,需要使用str(data,'gbk')来编码,因为windows中cmd窗口默认为GBK编码
注意:当传送数据超过1024字节时,会出现接收不完整,串行接收的情况
二、优化版本
如何确保完整接收服务器端返回的数据
优化方案:首先发送数据长度,客户端按照服务器端首次返回的数据长度去接收第二次返回的数据,
当分批次接收的数据累加长度为第一次返回的数据时,则意味着已经接收完毕
1.服务器端
1 #__author: Lobin 2 #__date: 2018/1/19 3 import subprocess 4 import socket 5 sk=socket.socket() 6 address=('127.0.0.1',8080) 7 sk.bind(address) 8 sk.listen(3) 9 while True: 10 conn,add=sk.accept() 11 print(conn,add) 12 while True: 13 try: 14 data=conn.recv(1024) 15 except Exception: 16 break 17 print('%s'%(str(data,'utf8'))) 18 if not data: 19 conn.close() 20 conn,add=sk.accept() 21 print(add) 22 continue 23 a=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE) 24 cmd_shell=a.stdout.read() 25 result_len=bytes(str(len(cmd_shell)),'utf8') 26 conn.send(result_len) 27 conn.send(cmd_shell) 28 sk.close()
传送的数据一定为bytes类型,分两次发送数据,一次数据为二次数据的长度
2.客户端
1 #__author: Lobin 2 #__date: 2018/1/19 3 import socket 4 sk=socket.socket() 5 address=('127.0.0.1',8080) 6 sk.connect(address) 7 while True: 8 inp=input('>>>') 9 if inp=='exit': 10 break 11 sk.send(bytes(inp,'utf8')) 12 result_len=int(str(sk.recv(1024),'utf8')) 13 print(result_len) 14 data=bytes() 15 while result_len!=len(data): 16 recv=sk.recv(1024) 17 data+=recv 18 print(str(data,'gbk')) 19 sk.close()
分两次接收,第一次数据为第二次接收数据的长度,初始化一个接收数据bytes类型
3.粘包现象
当连续两次send数据时,CPU可能将两次合并为一次来发送,故上述优化方法可能存在报错
解决方案为:在两次send中间插一条recv,当然客户端需要在第一次recv后加一个send任意数据
浙公网安备 33010602011771号