本文介绍客户端client输入dos指令,并将dos指令发送给服务端server,服务端接收到指令,通过调用subprocess模块的Popen方法实例化一个子进程对象,子进程对象执行完指令后,将结果并通过管道方式回送到主进程。其中,subprocess的用法,参见:Python subprocess模块解析。
一、通过发送字符串长度的方法:
1、服务端程序:cmd_server.py:
import socket import subprocess
import time # subprocess.Popen() 重要方法. # 学socket的秘籍:一收一发 sk = socket.socket() host='' #空表示本机,等效于127.0.0.1和localhost port=8000 address = (host,port) sk.bind(address) sk.listen(3) print('waiting......') # conn,addr = sk.accept() #这个conn是客户端的socket对象。非常重要。 while True: conn, addr = sk.accept() # 这个conn是客户端的socket对象。非常重要。 print(addr) while True: try: data = conn.recv(1024) except Exception: break if not data: #客户端退出时,最后还是会给服务端发送一个空串。即data为空。 break print('--------->',str(data,'utf8')) obj=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE) cmd_result = obj.stdout.read() #bytes类型 result_len = bytes(str(len(cmd_result)),'utf8') conn.sendall(result_len) #必须先传一个长度过去
# time.sleep(1) #两个发送指令send或sendall连在一起,会出现粘包现象。解决粘包现象,就是加入sleep
conn.recv(1024) #通过一收一发方式,多引入一个短收,解决粘包问题。
conn.sendall(cmd_result)
conn.close()
2、客户端程序:cmd_client.py:
import socket sk=socket.socket() address = ('127.0.0.1',8000) sk.connect(address) while True: inp = input('>>>') if inp=='exit': break sk.send(bytes(inp,'utf8')) result_len = int(str(sk.recv(1024),'utf8'))
sk.send(bytes('ok')) #用于解决粘包现象 print(result_len) data=bytes() #初始化一个bytes类型的变量,就像初始化sum=0一样 while len(data)!=result_len: temp = sk.recv(1024) data += temp print(str(data,'gbk')) sk.close()
二、更好的方法:
1、服务端程序:cmd_server.py:
import socket import subprocess # subprocess.Popen() 重要方法. # 学socket的秘籍:一收一发 sk = socket.socket() host='' #空表示本机,等效于127.0.0.1和localhost port=8000 address = (host,port) sk.bind(address) sk.listen(3) print('waiting......') # conn,addr = sk.accept() #这个conn是客户端的socket对象。非常重要。 while True: conn, addr = sk.accept() # 这个conn是客户端的socket对象。非常重要。 print(addr) while True: try: data = conn.recv(1024) except Exception: break if not data: #客户端退出时,最后还是会给服务端发送一个空串。即data为空。 break print('--------->',str(data,'utf8')) obj=subprocess.Popen(str(data,'utf8'),shell=True,stdout=subprocess.PIPE) cmd_result = obj.stdout.read() #bytes类型
# result_len = bytes(str(len(cmd_result)),'utf8')
# conn.sendall(result_len) #必须先传一个长度过去
# conn.recv(1024) #两个发送指令send或sendall连在一起,可能会出现粘包现象。解决粘包现象,就是加入临时阻塞
conn.sendall(cmd_result)
conn.close()
2、客户端程序:cmd_client.py
import socket sk=socket.socket() address = ('127.0.0.1',8000) sk.connect(address) buffersize=1024 while True: inp = input('>>>') if inp=='exit': break sk.send(bytes(inp,'utf8')) fullDataBtyes = b'' #初始化一个bytes类型的变量,等效于fullDataBytes=bytes()。 while True: data = sk.recv(buffersize) fullDataBtyes += data if len(data)<buffersize: break; print(str(fullDataBtyes,'gbk')) # result_len = int(str(sk.recv(1024),'utf8')) # sk.send(bytes('ok')) #解决粘包 # print(result_len) # data=bytes() #初始化一个bytes类型的变量,就像初始化sum=0一样 # while len(data)!=result_len: # temp = sk.recv(1024) # data += temp # print(str(data,'gbk')) sk.close()
参考:
1、‘’老男孩‘’python全栈开发,袁老师讲解
2、参考《python从菜鸟到高手》,作者:李宁