物联网 基于netty构建mqtt协议规范(轻量级二进制协议)
简述
在物联网、游戏服务器、RPC 等场景中,需要高效的网络通信。 二进制协议相比 JSON/XML 等文本协议,具有更小的体积、更快的解析速度、更低的内存占用等优势。 设计一个简单的二进制协议,并基于 Netty 实现完整的编解码器,深入理解二进制协议的开发流程
源码(netty-sample-03-Binary)
协议设计
类 MQTT 风格 的轻量级二进制协议
字段
字节数
描述
魔数 (Magic)
1
固定为 0xAA,用于快速校验和过滤非法连接
消息类型 (Type)
1
1=请求,2=响应,3=心跳
消息ID (MsgId)
4
大端序整数,用于请求-响应关联
数据长度 (Length)
2
无符号短整型(最大 65535),表示后面数据字段的字节数
数据 (Data)
Length
二进制数据(例如 UTF-8 字符串或其他内容)
协议总长度:1+1+4+2+Length = 8+Length 字节
优点
魔数帮助快速判断连接是否为合法客户端
长度字段为 2 字节,可表示最大 64KB 的消息体,适合小型物联网设备
消息 ID 使我们可以实现请求-响应的异步模型(如 RPC)
为什么二进制协议更轻量
特性
文本协议 (JSON)
二进制协议
数字编码
"123" 占用3字节
0x7B 占用1字节
布尔值
"true" 占用4字节
1位或1字节
字段名
每次重复发送
靠偏移量隐式约定
解析开销
字符串扫描、递归下降
按位移位、直接取值
示例:{"id":1}
8字节
若协议仅发送 id 数值,只需 4 字节(二进制 int)
server代码
java
package com.jysemel.iot.pojo;
import com.jysemel.iot.pojo.coder.BinaryMessageDecoder;
import com.jysemel.iot.pojo.coder.BinaryMessageEncoder;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
public class BinaryProtocolServer {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
// 添加二进制解码器和编码器
p.addLast(new BinaryMessageDecoder());
p.addLast(new BinaryMessageEncoder());
p.addLast(new ServerBusinessHandler());
}
});
ChannelFuture future = bootstrap.bind(8088).sync();
System.out.println("二进制协议服务器启动,端口 8088");
future.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
client代码
java
package com.jysemel.iot.pojo;
import com.jysemel.iot.pojo.coder.BinaryMessageDecoder;
import com.jysemel.iot.pojo.coder.BinaryMessageEncoder;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
public class BinaryProtocolClient {
public static void main(String[] args) throws InterruptedException {
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group)
.channel(NioSocketChannel.class)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new BinaryMessageDecoder());
p.addLast(new BinaryMessageEncoder());
p.addLast(new ClientBusinessHandler());
}
});
ChannelFuture future = bootstrap.connect("127.0.0.1", 8088).sync();
future.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
}
}
验证结果

