# 粘包:TCP协议为了提高网络性能,把时间间隔较小的两个数据粘到一起发送数据
# 1.发送端的send 与接收端的 rev 并非一一对应
# 2.接收端设置了最大包的bytes数,当大于这个数的数据被保存在接收端的内存中
# 3.余下的数据有可能与下一个数据包的数据粘到一起并连续显示
# 4.粘包并非必定发生,仅限于时间间隔较短的数据包才出现此情况
# 5.客户端服务端都有可能粘,其根本原因是:内存里还有残留数据包
# 解决方法:发送方 先通知 接收方 准备发送的数据包大小
# 客户端
import socket
import struct
import json
phone = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
phone.connect(('127.0.0.1', 8080))
while 1:
cmd = input()
phone.send(cmd.encode('utf-8'))
if not cmd:
continue
# 第一步 :收到报头长度
obj = phone.recv(4)
header_len = struct.unpack('i', obj)[0]
# 第二步 :收报头
header = phone.recv(header_len)
# 第三步:从报头取出信息
header_json = header.decode('uft-8')
header_dict = json.loads(header_json)
total_size = header_dict['total_zize']
# 第四步:接收真实的数据
recv_size = 0
recv_data = b''
while recv_size < total_size:
res = phone.recv(1024)
recv_data += res
recv_size += len(res)
print(recv_data.decode('utf-8'))
phone.close() # 4.关闭
# 服务端
import socket
import subprocess
import json
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 not close:
connect, client_addr = phone.accept()
while not disconnect:
try:
cmd = connect.recv(1024)
if not cmd:
break
obj = subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# 返回命令结果
# 第一步:报头
total_size = len(stdout)+len(stderr)
header_dict = {
'filename': 'a.txt',
'md5': 'xxdxxx',
'total_size': 3312312312313
}
header_json = json.dumps(header_dict).encode('uft-8')
# 第二步:制作 报头 的长度,并发送
header_len = struct.pack('i', len(header_json)) # i模式为int, l模式为long
conn.send(header_len)
# 第三步:把 报头 发送给客户端
connect.send(header_json)
# 第四步:发送真实数据
connect.send(obj.stdout.read())
connect.send(obj.stderr.read())
except ConnectionResetError:
disconnect = 1
connect.close()
phone.close()