发送时:
先发报头长度(dict->json.dumps序列号(json字符串)->bytes->struct.pack打包)
再编码报头内容然后发送(dict->json字符串->bytes)
最后发真实内容
接收时:
先接收报头长度,用struct取出来(struct.unpack解包)
根据取出的长度收取报头内容,然后解码,反序列化(解码->json.loads反序列化->dict)
从反序列化的结果中取出待取数据的描述信息,然后去取真实的数据内容
--------------------------------------tcp_server.py--------------------------------------
# coding:utf-8
import json
import struct
import socket
import subprocess
server = socket.socket()
ip_port = ("127.0.0.1", 8001)
server.bind(ip_port)
server.listen(5)
while 1:
conn, addr = server.accept()
from_client_msg = conn.recv(1024)
if not from_client_msg.decode("utf-8"):
break
print("来自客户端的消息:", from_client_msg.decode("utf-8"))
res = subprocess.Popen(
from_client_msg.decode("utf-8"),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
cmd_result = res.stderr.read()
if not cmd_result:
cmd_result = res.stdout.read()
cmd_result_len = len(cmd_result) # 数据的长度
headers = {"data_size": cmd_result_len} # 报头信息(dict类型)
header_json = json.dumps(headers) # 报头信息(json字符串)
header_json_bytes = bytes(header_json, encoding="utf-8") # 报头信息(bytes类型)
conn.send(struct.pack('i', len(header_json_bytes))) # 先发送报头的长度
conn.send(header_json_bytes) # 再发送报头的内容
conn.sendall(cmd_result) # 最后发送数据
conn.close()
server.close()
--------------------------------------tcp_client.py--------------------------------------
# coding:utf-8
import json
import struct
import socket
client = socket.socket()
ip_port = ("127.0.0.1", 8001)
client.connect(ip_port)
while 1:
cmd = input(">>>: ").strip()
if not cmd: continue
client.send(cmd.encode("utf-8"))
from_server_head_msg_len = client.recv(4) # 先接收报头的长度(bytes类型)
from_server_head_msg_len = struct.unpack('i', from_server_head_msg_len) # 解包(tuple类型)
print("来自服务端的消息:", from_server_head_msg_len[0]) # 元组的第一个元素为报头的长度
from_server_head_msg = client.recv(from_server_head_msg_len[0]) # 接收报头信息
from_server_head_msg = from_server_head_msg.decode("utf-8") # 报头信息解码
from_server_head_msg = json.loads(from_server_head_msg) # 报头信息转化为dict类型
print("来自服务端的消息:", from_server_head_msg)
from_server_real_msg = client.recv(1024) # 接收真正的数据
from_server_real_len = len(from_server_real_msg) # 获取一次接收数据的大小
while from_server_head_msg['data_size'] > from_server_real_len: # 判断数据是否接收完整
from_server_real_msg += client.recv(1024) # 再次接收没接收完的数据
from_server_real_len = len(from_server_real_msg) # 再次统计已接收数据的大小
print("来自服务端的消息:", from_server_real_msg.decode("gbk"))
client.close()