先传包头的长度,再解包头从包头中取包的长度,来精准解析包内容
<引子> 远程执行ssh命令模块
import subprocess
obj = subprocess.Popen('d2ir', shell = True,
stdout = subprocess.PIPE,
stderr= subprocess.PIPE)
print('sudout>:', obj.stdout.read().decode('GBK'))
print('stderr>:', obj.stderr.read().decode('GBK'))
<引子> 利用struct 和 json 模块完成自定义包头传输
import struct
res = struct.pack('i',128)
res = struct.pack('l',128)
<引子> windows ssh默认编码 GBK liunx为 utf-8!!!!
服务端
import socket
import subprocess
import struct
import json
obj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
obj.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
obj.bind(('127.0.0.1', 8084))
obj.listen(5)
while True:
conn, ip= obj.accept()
print('用户接入:',ip)
while True:
try:
''''【一】 接收命令'''
cmd = conn.recv(1024)
if not cmd:break
print('接收到用户指令',cmd)
''''【二】执行命令'''
sub = subprocess.Popen(cmd.decode('GBK'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout = sub.stdout.read()
stderr = sub.stderr.read()
''''【三】把结果返回传给客户端'''
header_dic = {
'filename':'测试.txt',
'md5':'这里可以放md5',
'total_size': len(stdout)+len(stderr)
}
header_json = json.dumps(header_dic)
header_byte = header_json.encode('gbk')
'''如果直接把包头发过去,长度可能会超出struct模块的'i'和'l'模式的长度,所以最稳的方法是,把包头长度先传过去,再传包头,这样就能精准传输'''
conn.send(struct.pack('i',len(header_byte)))
conn.send(header_byte)
conn.send(stdout)
conn.send(stderr)
except ConnectionResetError:
print('该客户断开已断开连接')
break
conn.close()
print('关闭管道')
obj.close()
客户端
import json
import socket
import struct
obj = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
obj.connect(('127.0.0.1', 8084))
while True:
'''【一】发命令'''
cmd = input('请输入指令>>>').strip()
if not cmd:
continue
obj.send(cmd.encode('GBK'))
'''【二】接收数据 解决粘包问题'''
header_size = struct.unpack('i', obj.recv(4))[0]
header_bytes = obj.recv(header_size)
header_json = header_bytes.decode('gbk')
header_dic = json.loads(header_json)
total_size = header_dic.get('total_size')
print('包头信息', header_dic)
recv_size = 0
recv_data = b''
while recv_size < total_size:
res = obj.recv(1024)
recv_data += res
recv_size += len(res)
print(recv_data.decode('GBK'))
obj.close()