为什么会存在粘包问题?
因为tcp是流失协议 因为接收方不知道发送方的的数据总量和数据划分的界限,
解决的思路:
接收方需要先获取数据的长度
需要发送方先发送数据的长度给接收方
接收方收到长度之后 按照数据长度来获取数据
struct 模块
可以将python中的数据类型 转换成bytes
第一个参数通常是i 其能转换的数据范围是c语言的int范围
如果int不够 那就用q 表示long long 型
num = 1024
res = struct.pack("i",num) 转成固定4位的bytes字节
res2 = struct.unpack("i",res) 从字节转回整型
服务器端 import socket import subprocess import struct import datetime import json server =socket.socket() server.bind(('127.0.0.1',16888)) server.listen() # 要求 不仅返回命令的结果 还要返回执行命令的时间 执行时间:2018/12/26 while True: client,addr = server.accept() while True: try: #接收命令 cmd = client.recv(1024).decode('utf-8') p = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) data = p.stdout.read() err_data = p.stderr.read() length = len(data)+len(err_data) #真实数据长度 # 在发送数据之前发送额外的信息 # t = "{执行时间:%s 真实数据长度:%s" % (datetime.datetime.now(),length) # 把要发送的数据先存到字典中 t ={} t["time"] = str(datetime.datetime.now()) t["size"] = length t["filename"] = "a.mp4" t_json = json.dumps(t) t_data = t_json.encode('utf-8') t_length = struct.pack('i',len(t_data)) client.send(t_length) #1.先发送额外信息的长度 client.send(t_data) #2.再发送额外信息 client.send(data) #3.发送真实信息 client.send(err_data) except ConnectionResetError: client.close() print('客户端关闭,连接中断') break
客户端 import socket import struct import json c = socket.socket() c.connect(('127.0.0.1',16888)) while True: cmd = input(">>>>>:") if not cmd : print('命令符不能为空') continue c.send(cmd.encode('utf-8')) #接收额外信息的长度 length = c.recv(4) len_data = struct.unpack('i',length)[0] #接收到的是(72,) 这样类型的元组 取到长度 72 #接收额外信息 t_data = c.recv(len_data) json_dic = json.loads(t_data.decode("utf-8")) print('执行时间%s:'%json_dic["time"]) data_size = json_dic["size"] #得到数据长度 #开始接收真实的数据 all_data = b'' #储存已经接收到的数据 rcv_size = 0 #已经接收长度 while rcv_size < data_size: data = c.recv(1024) rcv_size +=len(data) all_data += data print('接收长度%s'%rcv_size) print(all_data.decode('gbk'))