1. struct
struct.pack 打包
def pack(fmt, *args): # known case of _struct.pack """ pack(fmt, v1, v2, ...) -> bytes Return a bytes object containing the values v1, v2, ... packed according to the format string fmt. See help(struct) for more on format strings. """ return b""
struct.unpack 解包
def unpack(fmt, string): # known case of _struct.unpack """ unpack(fmt, buffer) -> (v1, v2, ...) Return a tuple containing values unpacked according to the format string fmt. The buffer's size in bytes must be calcsize(fmt). See help(struct) for more on format strings. """ pass
fmt 长度表
# 粘包解决方案_3_服务端 struct.pack 打包 import socket import struct import subprocess import time server = socket.socket() ip_port = ('192.168.15.87', 8001) server.bind(ip_port) server.listen(3) while 1: print('等待连接中...') conn, addr = server.accept() print('连接成功!') while 1: print('等待接收命令...') cmd = conn.recv(1024).decode('utf-8') if cmd == 'exit': break sub_obj = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) # 调用控制台, stdout标准输出,返回信息 stderr 标准错误,返回错误信息 content = sub_obj.stdout.read() # 读取标准输出,获取到是gbk编码的bytes error = sub_obj.stderr.read() # 读取标准错误, 也是gbk编码的bytes len_of_content = len(content) # 获取标准输出长度 len_packed = struct.pack('i', len_of_content) # 'i'表示打包成4个字节长度. 此处将数据长度打包成4个字节长度的数据 len_of_err = len(error) # 获取标准错误长度 len_err_packed = struct.pack('i', len_of_err) # 'i' 表示打包成4个字节长度. 此处将错误信息长度打包成4个字节长度的数据 # print(len_packed) # 显示的是字节 b'\xaf\x01\x00\x00' if len_of_content == 0: # 当标准输出长度是零,也就是返回错误信息的时候 conn.send(len_err_packed) # 发送打包后的错误信息的长度 print('数据长度发送成功!') conn.sendall(error) # 循环着发送错误信息数据,防止数据过大造成缓冲区溢出 # 缓冲区大小 8kb MTU 最大传输单元 1518b, 每次发送数据最好不超过这个数 print('数据发送成功!') else: conn.send(len_packed) # 发送打包后的标准输出信息长度 print('数据长度发送成功!') # 循环着发送标准输出信息数据,防止数据过大造成缓冲区溢出 conn.sendall(content) print('数据发送成功!') conn.close() print('连接已断开!') time.sleep(3)
# 粘包解决方案_3_客户端 struct.unpack 解包 import socket import struct client = socket.socket() serverip_port = ('192.168.15.87', 8001) client.connect(serverip_port) while 1: cmd = input('请输入命令>>>') client.send(cmd.encode('utf-8')) if cmd == 'exit': break msg_len_return = client.recv(4) # 先接收4个字节长度的打包信息 msg_return_unpacked = struct.unpack('i', msg_len_return)[0] # 拆包, 获取数据长度 # print(msg_return_unpacked) # struct.unpack('i', msg_len_return)返回一个元组 (431,), 取[0]得到长度431 total_len = 0 total_data = b'' while total_len < msg_return_unpacked: data_splited = client.recv(1024) # 分段接收信息,一次最多接收1024,防止超过MTU total_data += data_splited # 把接收到的数据拼接到一起 total_len += len(data_splited) # 计算接收到的数据总长度 print(total_data.decode('gbk')) # 接收到的信息都是gbk编码的bytes,需要进行解码 client.close()
2. FTP 简单上传
3. socketserver