当前位置: 首页 > news >正文

springboot 作为客户端接收服务端的 tcp 长连接数据,并实现自定义结束符,解决 粘包 半包 问题

博主最近的项目对接了部分硬件设备,其中有的设备只支持tcp长连接方式传输数据,博主项目系统平台作为客户端发起tcp请求到设备,设备接收到请求后作为服务端保持连接并持续发送数据到系统平台。

1.依赖引入

连接使用了netty,如果项目中没有就先引入:

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.69.Final</version>
</dependency>

2.创建客户端

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import lombok.extern.slf4j.Slf4j;import java.nio.charset.StandardCharsets;/*** @author GBX* @description tcp长连接客户端* @date 2024/5/29 15:11*/
@Slf4j
public class NettyTcpClient {private final Bootstrap bootstrap;private final EventLoopGroup group;private Channel channel;public NettyTcpClient(String host, int port) {group = new NioEventLoopGroup();bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ChannelPipeline pipeline = ch.pipeline();//添加自定义结束规则pipeline.addLast(new DelimiterBasedFrameDecoder(1024, ByteBufAllocator.DEFAULT.buffer().writeBytes("|".getBytes(StandardCharsets.UTF_8))));//添加自定义消息处理器pipeline.addLast(new TcpClientHandler());}});try {channel = bootstrap.connect(host, port).sync().channel();log.info("NettyTcpClient ===》 success");} catch (Exception e) {log.error("NettyTcpClient-发生异常, 信息:", e);}}public void close() {if (channel != null) {channel.close();}group.shutdownGracefully();}public static class TcpClientHandler extends SimpleChannelInboundHandler<ByteBuf> {@Overrideprotected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {//处理接收到的数据System.out.println("Received data ===>: " + msg.toString(StandardCharsets.UTF_8));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}}
}

如上代码中所示,博主使用了 “|” 作为结束符,使用结束符可以有效地解决tcp数据读取的粘包 半包问题。

3.设置配置类以进行自启动

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @author GBX* @description tcp长连接配置类* @date 2024/5/29 15:14*/
@Configuration
public class NettyClientConfig {@Bean(destroyMethod = "close")public NettyTcpClient nettyTcpClient() {NettyTcpClient client = new NettyTcpClient("127.0.0.1", 4001);// 启动客户端连接return client;}
}

4.效果测试

启动项目,发现客户端连接远程成功:

远程服务器端,这里使用的是 NetAssist 工具进行模拟(注意:该工具在springboot项目启动前已经提前启动了服务器模式进行了端口监听,可以看到项目启动后进来一个连接):

如上图所示,在8 和 10 后分别由一个结尾符,在工具上发送数据:

在springboot控制台可以看到打印的信息为两条:

工具可以在网盘下载:

链接: https://pan.baidu.com/s/1UccmnEL4VktHTHL7P_2V_g?pwd=6fcw 提取码: 6fcw

http://www.lryc.cn/news/364056.html

相关文章:

  • kuka编程怎么加中文:解锁KUKA机器人编程中的中文支持
  • hadoop集群中zookeeper的搭建与原理解释
  • HTML静态网页成品作业(HTML+CSS)—— 父亲节节日介绍网页(4个页面)
  • Client ID 与Client Secret
  • React中实现大模型的打字机效果
  • 十二、配置注解执行SQL
  • 阿里云计算之运维概念学习笔记(一)
  • 异常概述
  • 【Postman接口测试】第五节.Postman接口测试项目实战(下)
  • 医用腕带朔源用的条形码与二维码如何选择
  • “Kubectl 如何工作案例:编写自定义 Kubectl 命令
  • opencv-python(五)
  • 免费生物蛋白质的类chatgpt工具助手copilot:小分子、蛋白的折叠、对接等
  • Mybatis01-初识Mybatis
  • 算法课程笔记——基础数据结构 堆
  • 边缘数据采集网关为企业提供高效、安全、可靠的数据采集解决方案-天拓四方
  • 鸿蒙开发接口安全:【@ohos.security.huks (通用密钥库系统)】
  • 黄仁勋:打破摩尔定律,机器人时代来了
  • 每天的CTF小练--6.5(ascll码高级运用)
  • docker参数大P与小p的区别
  • 智慧启航 网联无限丨2024高通汽车技术与合作峰会美格智能分论坛隆重举行
  • 20.Redis之缓存
  • vue中实现一个时间选择器的级联框,第一层小时,第二层分钟
  • 数据分析必备:一步步教你如何用Pandas做数据分析(17)
  • 检查用户是否在错误的目录中运行了CMake命令
  • 前端工程化工具系列(四)—— Commitlint(v19.3.0):规范化 Git 提交
  • <vs2022><问题记录>visual studio 2022使用console打印输出时,输出窗口不显示内容
  • 推荐一个免费的相亲工具
  • 写一个盲盒模拟器
  • Java使用正则表达式匹配以某个字符开始,某个字符结束