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任意数据

posted on 2018-01-20 01:24  可爱的春哥  阅读(224)  评论(0)    收藏  举报

导航