网上做论文的网站,鞍山人才网怎么查档案,什么是网络营销工具,做html网站SpringBoot 集成Netty实现TCP/UDP通信协议【优化版】 引言 在现代物联网(IoT)应用中#xff0c;设备与服务器之间的实时通信至关重要。Netty作为一个高性能的网络应用框架#xff0c;与SpringBoot的集成可以简化开发过程#xff0c;并提高应用性能。本文将详细介绍如何在S…SpringBoot 集成Netty实现TCP/UDP通信协议【优化版】引言在现代物联网(IoT)应用中设备与服务器之间的实时通信至关重要。Netty作为一个高性能的网络应用框架与SpringBoot的集成可以简化开发过程并提高应用性能。本文将详细介绍如何在SpringBoot中集成Netty实现TCP和UDP通信协议。通讯协议在设计通讯协议时我们考虑了数据的完整性和命令的明确性。以下是我们的协议设计字段名字节数组下标字节长度说明flagbyte[0]-byte[3]4byte固定包头标识使用9527作为固定包头cmdbyte[4]1byte通讯命令operatebyte[5]1byte操作11-发送请求需要回复12-发送请求不需要回复21-回复操作成功22-回复操作失败lengthbyte[6]-byte[7]2byte数据长度(从包头固定标识开始计算总字节数)msgNobyte[8]1byte消息编号(1-255)核心代码3.1 Netty 服务器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; /** * 初始化雷达UDP服务 */ 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(); } /** * 启动服务 */ public void start() throws InterruptedException { EventLoopGroup mainGroup new NioEventLoopGroup(2); EventLoopGroup workGroup new NioEventLoopGroup(8); Bootstrap bootstrap new Bootstrap(); bootstrap.group(mainGroup) .channel(NioDatagramChannel.class) .option(ChannelOption.SO_BROADCAST, true) .option(ChannelOption.SO_RCVBUF, 1024 * 1024 * 10) .option(ChannelOption.SO_SNDBUF, 1024 * 1024 * 10) .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT) .localAddress(new InetSocketAddress(nettyPort)) .handler(new ChannelInitializerNioDatagramChannel() { Override protected void initChannel(NioDatagramChannel nioDatagramChannel) throws Exception { nioDatagramChannel.pipeline() .addLast(workGroup, udpRadarNettyServerHandler); } }); ChannelFuture future bootstrap.bind().sync(); this.channel future.channel(); log.info(---------- [init] UDP Radar netty server start, port:{} ----------, nettyPort); } public Channel getChannel() { return this.channel; } }3.2 Netty 服务端工具类package com.ljq.demo.springboot.netty.server.util; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import com.ljq.demo.springboot.netty.server.init.UdpRadarNettyServer; import com.ljq.demo.springboot.netty.server.model.response.UdpRadarHeader; import io.netty.buffer.Unpooled; import io.netty.channel.socket.DatagramPacket; import lombok.extern.slf4j.Slf4j; import java.net.InetSocketAddress; import java.util.Objects; /** * UDP雷达服务端工具类 */ Slf4j public class UdpRadarServerUtil { public static final int HEADER_BYTE_LENGTH 9; public static final int HEADER_DATA_LENGTH 18; public static final int MSG_MAX_LENGTH 1000; public static final String HEADER_FLAG 39353237; private UdpRadarServerUtil() { } /** * 校验服务端接收到的数据是否合法 * * param hexMsg 十六进制消息 * return 是否合法 */ public static boolean validate(String hexMsg) { if (StrUtil.isBlank(hexMsg) || hexMsg.length() HEADER_DATA_LENGTH || hexMsg.length() MSG_MAX_LENGTH || !hexMsg.startsWith(HEADER_FLAG)) { return false; } return true; } /** * 解析请求头 * * param hexMsg 十六进制消息 * return 请求头对象 */ public static UdpRadarHeader parseHeader(String hexMsg) { UdpRadarHeader header new UdpRadarHeader(); header.setFlag(HexUtil.decodeHexStr(hexMsg.substring(0, 8))); header.setCmd(HexUtil.hexToInt(hexMsg.substring(8, 10))); header.setOperate(HexUtil.hexToInt(hexMsg.substring(10, 12))); header.setLength(HexUtil.hexToInt(hexMsg.substring(12, 16))); header.setMsgNo(HexUtil.hexToInt(hexMsg.substring(16, 18))); return header; } /** * 生成发送数据(仅请求头) * * param header 请求头对象 * return 十六进制数据 */ public static String getHexData(UdpRadarHeader header) { StringBuilder dataBuilder new StringBuilder(); dataBuilder.append(HexUtil.encodeHexStr(header.getFlag())); dataBuilder.append(String.format(%02x, header.getCmd())); dataBuilder.append(String.format(%02x, header.getOperate())); dataBuilder.append(String.format(%04x, header.getLength())); dataBuilder.append(String.format(%02x, header.getMsgNo())); return dataBuilder.toString(); } /** * 生成发送数据(包含业务数据) * * param header 请求头对象 * param data 业务数据 * return 十六进制数据 */ public static String getHexData(UdpRadarHeader header, String data) { StringBuilder dataBuilder new StringBuilder(getHexData(header)); if (StrUtil.isNotBlank(data)) { dataBuilder.append(HexUtil.encodeHexStr(data)); } return dataBuilder.toString(); } /** * 向客户端发送数据 * * param clientIp 客户端IP * param clientPort 客户端端口 * param hexMsg 十六进制消息 */ public static void sendData(String clientIp, int clientPort, String hexMsg) { UdpRadarNettyServer udpRadarNettyServer SpringUtil.getBean(UdpRadarNettyServer.class); if (Objects.isNull(udpRadarNettyServer)) { log.warn(UDP Radar Server is not running); return; } DatagramPacket sendPacket new DatagramPacket(Unpooled.copiedBuffer(Convert.hexToBytes(hexMsg)), new InetSocketAddress(clientIp, clientPort)); udpRadarNettyServer.getChannel().writeAndFlush(sendPacket); } /** * 向客户端发送数据 * * param clientId 客户端ID * param clientPort 客户端端口 * param header 请求头对象 * param data 业务数据 */ public static void sendData(String clientId, int clientPort, UdpRadarHeader header, String data) { String hexMsg getHexData(header, data); sendData(clientId, clientPort, hexMsg); } }3.3 Netty 服务处理器package com.ljq.demo.springboot.netty.server.handler; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.RandomUtil; import com.ljq.demo.springboot.netty.server.model.response.UdpRadarHeader; import com.ljq.demo.springboot.netty.server.util.UdpRadarServerUtil; import io.netty.buffer.ByteBufUtil; import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.socket.DatagramPacket; import io.netty.util.concurrent.DefaultThreadFactory; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import java.net.InetSocketAddress; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util .concurrent.TimeUnit; /** * UDP雷达服务端处理器 */ Slf4j Component ChannelHandler.Sharable public class UdpRadarNettyServerHandler extends SimpleChannelInboundHandlerDatagramPacket { private final ExecutorService executorService new ThreadPoolExecutor(4, 8, 60, TimeUnit.SECONDS, new LinkedBlockingQueue(10000), new DefaultThreadFactory(UDP-Radar-work-pool), new ThreadPoolExecutor.CallerRunsPolicy()); Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception { String hexMsg ByteBufUtil.hexDump(packet.content()).toUpperCase(); if (!UdpRadarServerUtil.validate(hexMsg)) { log.info(invalid data); return; } InetSocketAddress clientAddress packet.sender(); executorService.execute(() - { UdpRadarHeader header UdpRadarServerUtil.parseHeader(hexMsg); log.info(UDP Radar server receive msg,client: {},cmd:{},operate:{}, clientAddress.getHostString(), header.getCmd(), header.getOperate()); String responseHexMsg demoService(hexMsg); if (Objects.equals(11, header.getOperate())) { UdpRadarServerUtil.sendData(clientAddress.getHostString(), clientAddress.getPort(), responseHexMsg); } }); } /** * 示例业务方法 * * param hexMsg 十六进制消息 * return 响应的十六进制消息 */ private String demoService(String hexMsg) { UdpRadarHeader header UdpRadarServerUtil.parseHeader(hexMsg); UdpRadarHeader responseHeader new UdpRadarHeader(); responseHeader.setCmd(header.getCmd()); responseHeader.setOperate(21); responseHeader.setLength(UdpRadarServerUtil.HEADER_BYTE_LENGTH 5); responseHeader.setMsgNo(header.getMsgNo()); StringBuilder responseHexMsgBuilder new StringBuilder(); responseHexMsgBuilder.append(UdpRadarServerUtil.getHexData(responseHeader)); responseHexMsgBuilder.append(String.format(%02x, RandomUtil.randomInt(0, 128))); responseHexMsgBuilder.append(HexUtil.encodeHexStr(RandomUtil.randomString(4))); return responseHexMsgBuilder.toString(); } }3.4 协议请求头封装类package com.ljq.demo.springboot.netty.server.model.response; import lombok.Data; import java.io.Serializable; /** * UDP雷达请求头参数 */ Data public class UdpRadarHeader implements Serializable { private static final long serialVersionUID 4765355155562316019L; /** * 固定包头标识(4byte) */ private String flag 9527; /** * 命令(1byte) */ private Integer cmd; /** * 操作11-发送请求需要回复12-发送请求不需要回复21-回复操作成功22-回复操作失败(1byte) */ private Integer operate; /** * 数据长度(从包头固定标识开始计算总字节数)(2byte) */ private Integer length; /** * 消息编号(1-255)(1byte) */ private Integer msgNo; }测试4.1 测试工具推荐使用NetAssist网络调试助手来模拟设备发送TCP/UDP指令。下载NetAssist4.2 测试数据原始发送数据{ flag: 9527, cmd: 20, operate: 11, length: 9, msgNo: 85 }编码后的发送数据39353237140b000955后台日志2024-08-20 09:52:41 | INFO | UDP-Radar-work-pool-3-1 | com.ljq.demo.springboot.netty.server.handler.UdpRadarNettyServerHandler 55| UDP Radar server receive msg,client: 192.168.15.32,cmd:20,operate:11扩展阅读和资源链接Netty官方文档SpringBoot官方文档通过本篇文章您能学到什么通过阅读本篇文章您将获得以下知识和技能Netty与SpringBoot集成的理解您将了解如何将Netty框架集成到SpringBoot应用中以及这种集成如何简化物联网通信的开发。TCP/UDP通信协议的实现您将学会如何在Netty中实现TCP和UDP通信协议包括如何配置服务器以及如何处理网络数据。自定义通信协议的设计您将掌握如何设计自定义的通信协议包括数据包的结构和字段定义以及如何确保数据的完整性和命令的明确性。数据编码与解码您将学习如何将数据编码为Hex格式进行传输以及如何将接收到的Hex数据解码回原始格式。网络编程实践您将获得实际的网络编程经验包括如何处理网络连接、数据传输和异常情况。测试工具的使用您将学会如何使用NetAssist这样的网络调试助手来模拟设备发送TCP/UDP指令以及如何进行网络通信的测试。问题解决技巧您将了解一些调试技巧和常见问题的解决方案帮助您在开发过程中快速定位和解决问题。代码阅读与理解通过分析和理解文章中提供的代码示例您将提高代码阅读能力这对于学习和工作中的代码审查都是非常有益的。高性能网络应用开发您将掌握使用Netty开发高性能网络应用的技巧这对于需要处理大量并发网络连接的应用尤为重要。资源链接与扩展学习文章最后提供的资源链接将引导您进行更深入的学习无论是Netty的高级特性还是SpringBoot的最佳实践您都能找到进一步学习的途径。通过本篇文章的学习您不仅能够获得理论知识还能够通过实践加深理解为将来在物联网领域的网络通信开发打下坚实的基础。你掌握了那些或遇到那些问题欢迎评论留言进行讨论