文章目录
1 摘要
在 IoT 物联网设备通讯领域,服务端和设备端的通讯通常基于 TCP/UDP 协议,在这些协议的基础上定义自己的私有通讯协议。本文将介绍 SpringBoot 集成 Netty 在服务端常用的TCP、UDP通讯协议示例。
SpringBoot 集成 Netty 作为服务端:
SpringBoot 2.7 集成 Netty 4 模拟服务端与客户端通讯入门教程
SpringBoot 2.7 集成 Netty 4 实现 UDP 通讯
2 通讯协议
字段名 | 字节数组下标 | 字节长度 | 说明 |
---|---|---|---|
flag | byte[0]-byte[3] | 4byte | 固定包头标识,使用"9527"作为固定包头 |
cmd | byte[4] | 1byte | 通讯命令 |
operate | byte[5] | 1byte | 操作,11-发送请求,需要回复;12-发送请求,不需要回复;21-回复操作成功,22-回复操作失败 |
length | byte[6]-byte[7] | 2byte | 数据长度(从包头固定标识开始计算,总字节数) |
msgNo | byte[8] | 1byte | 消息编号(1-255) |
传输数据格式按照 Hex 数据格式进行传输
以上为数据包头部分协议,内容数据拼接在包头后边。
示例:
只包含请求头的原始数据:
{
"flag": "9527",
"cmd": 20,
"operate": 11,
"length": 9,
"msgNo": 85
}
编码后数据:
39353237140b000955
包含内容的原始数据:
{
"flag": "9527",
"cmd": 20,
"operate": 11,
"length": 12,
"msgNo": 85,
"data": "123"
}
编码后数据:
39353237140b000c55313233
3 核心代码
3.1 Netty 服务器
./demo-netty-server/src/main/java/com/ljq/demo/springboot/netty/server/init/UdpRadarNettyServer.java
package com.ljq.demo.springboot.netty.server.init;
import com.ljq.demo.springboot.netty.server.handler.UdpRadarNettyServerHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.net.InetSocketAddress;
/**
* @Description: 初始化雷达 udp 服务
* @Author: Mr.lu
* @Date: 2024/8/15
*/
@Slf4j
@Component
public class UdpRadarNettyServer implements ApplicationRunner {
@Value("${netty.portUdpRadar:9135}")
private Integer nettyPort;
@Resource
private UdpRadarNettyServerHandler udpRadarNettyServerHandler;
/**
* 通道
*/
private Channel channel;
@Override
public void run(ApplicationArguments args) throws Exception {
this.start();
}
/**
* 启动服务
*
* @throws InterruptedException
*/
public void start() throws InterruptedException {
// 连接管理线程池
EventLoopGroup mainGroup = new NioEventLoopGroup(2);
EventLoopGroup workGroup = new NioEventLoopGroup(8);
// 工作线程池
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(mainGroup)
// 指定 nio 通道,支持 UDP
.channel(NioDatagramChannel.class)
// 广播模式
.option(ChannelOption.SO_BROADCAST, true)
// 设置读取缓冲区大小为 10M
.option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 10)
// 设置发送缓冲区大小为 10M
.option(ChannelOption.SO_SNDBUF, 1024 * 1024 * 10)
// 线程池复用缓冲区
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
// 指定 socket 地址和端口
.localAddress(new InetSocketAddress(nettyPort))
// 添加通道 handler
.handler(new ChannelInitializer