服务端
import json
import socket
import struct
import subprocess
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
phone.bind(('127.0.0.1', 8080))
phone.listen(5)
while 1:
conn, addr = phone.accept()
while 1:
try:
data = conn.recv(1024)
print(data)
res = subprocess.Popen(data.decode('utf-8'), shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout = res.stdout.read()
stderr = res.stderr.read()
# 定制报头
header_dict = {
'total_size': len(stdout) + len(stderr),
'filename': None
}
header_bytes = json.dumps(header_dict).encode('utf-8')
# 发送报头长度
header_len = struct.pack('i', len(header_bytes))
conn.send(header_len)
# 发送报头
conn.send(header_bytes)
conn.send(res)
# 发送数据部分
conn.send(stdout)
conn.send(stderr)
except Exception:
break
conn.close()
phone.close()
客户端
import json
import socket
import struct
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))
while 1:
cmd = input('请输入>>:').strip()
if not cmd: continue
phone.send(cmd.encode('utf-8'))
# 接收报头长度
res = phone.recv(4)
# 对报头长度解压
header_size = struct.unpack('i', res)[0]
# 接收报头长度的内容
header_bytes = phone.recv(header_size).decode('utf-8')
# 对报头字典进行反序列化
header_json = json.load(header_bytes)
# 获取数据长度
data_size = header_json['total_size']
# 根据报头数据长度对数据进行接收
recv_size = 0
total_data = b''
while recv_size < data_size:
data_recv = phone.recv(1024)
if (data_size - len(data_recv)) < 1024:
left_data = phone.recv(data_size - len(data_recv))
total_data += left_data
total_data += data_recv
recv_size += len(data_recv)
print(total_data.decode('gbk'))
phone.close()
大体思路就是服务端将报头信息进行优化,对要发送的内容用字典进行描述,首先字典不能直接进行网络传输,需要进行序列化转成json格式字符串,然后转成bytes格式服务端进行发送,因为bytes格式的json字符串长度不是固定的,所以要用struct模块把bytes格式的json字符串长度压缩成固定长度,发送给客户端。客户端进行接收,反解就会得到完整的数据包。