今日内容:
1、流式协议=》粘包问题(***)
解决方案:自定义应用层协议
注意:
head+data
head的长度必须固定
# 粘包问题
'''
import subprocess
import struct
import socket
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, client_addr = server.accept()
while True:
try:
cmd = conn.recv(1024)
print('收到的客户端数据:', cmd.decode('utf-8'))
obj = subprocess.Popen(cmd.decode('utf-8'),
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
stdout = obj.stdout.read()
stderr = obj.stderr.read()
total_size = len(stdout) + len(stderr)
# 先发送数据的长度
conn.send(struct.pack('i', total_size))
# 发送实际数据
conn.send(stdout)
conn.send(stderr)
except Exception:
break
conn.close()
server.close()
'''
'''
import struct
from socket import *
client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
cmd = input('>>>:').strip()
if len(cmd) == 0:
continue
client.send(cmd.encode('utf-8'))
# 先接受数据的长度
n = 0
header = b''
while n < 4:
data = client.recv(1)
header += data
n += len(data)
total_size = struct.unpack('i',header)[0]
recv_size = 0
res = b''
while recv_size < total_size:
data = client.recv(1024)
res += data
recv_size += len(data)
print(res.decode('gbk'))
client.close()
'''
# 定制复杂的报头
'''
import os
import struct
from socket import *
server = socket(AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, client_addr = server.accept()
print(conn)
print(client_addr)
while True:
try:
msg = conn.recv(1024).decode('utf-8')
cmd, file_path = msg.split()
if cmd == 'get':
# 先发送报头
total_size = os.path.getsize(file_path)
conn.send(struct.pack('i', total_size))
with open(r'%s' % file_path, mode='rb') as f:
for line in f:
conn.send(line)
except Exception:
break
conn.close()
server.close()
'''
'''
import struct
from socket import *
client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
cmd = input('要复制的文件(先输入get):').strip()
if len(cmd) == 0:
continue
client.send(cmd.encode('utf-8'))
# 先接收数据长度
n = 0
header = b''
while n < 4:
data = client.recv(1)
header += data
n += len(data)
total_size = struct.unpack('i', header)[0]
print(total_size)
# 接收数据
data_size = 0
with open('copy.jpg', mode='wb') as f:
while data_size < total_size:
data = client.recv(1024)
f.write(data)
data_size += len(data)
client.close()
'''
'''
import os
import struct
import json
from socket import *
server = socket(AF_INET, SOCK_STREAM)
server.bind(('127.0.0.1', 8080))
server.listen(5)
while True:
conn, client_addr = server.accept()
while True:
try:
msg = conn.recv(1024).decode('utf-8')
cmd, file_path = msg.split()
if cmd == 'get':
# 制作报头
header_dic = {
'total_size': os.path.getsize(file_path),
'file_name': os.path.basename(file_path),
'md5': '11111111111111'
}
header_json = json.dumps(header_dic)
header_json_bytes = header_json.encode('utf-8')
# 发送数据
# 1、先发送报头长度
header_size = len(header_json_bytes)
conn.send(struct.pack('i', header_size))
# 再发送报头
conn.send(header_json_bytes)
# 最后发送真实的数据
with open(r'%s' % file_path, mode='rb') as f:
for line in f:
conn.send(line)
except Exception:
break
conn.close()
server.close()
'''
'''
import struct
import json
from socket import *
client = socket(AF_INET, SOCK_STREAM)
client.connect(('127.0.0.1', 8080))
while True:
cmd = input('复制的文件(先输入get):').strip()
if len(cmd) == 0:
continue
client.send(cmd.encode('utf-8'))
# 1、先接收报头的长度
res = client.recv(4)
header_size = struct.unpack('i', res)[0]
# 2、再接收报头
header_json_bytes = client.recv(header_size)
header_json = header_json_bytes.decode('utf-8')
header_dic = json.loads(header_json)
# 3、最后接收数据
total_size = header_dic['total_size']
file_name = header_dic['file_name']
recv_size = 0
with open(file_name, mode='wb') as f:
while recv_size < total_size:
data = client.recv(1024)
f.write(data)
recv_size += len(data)
client.close()
'''
struct模块
该模块可以把一个类型,如数字,转成固定长度的bytes
>>> struct.pack('i',1111111111111)
。。。。。。。。。
struct.error: 'i' format requires -2147483648 <= number <= 2147483647 #这个是范围
![]()