赞
踩
博主最近的项目对接了部分硬件设备,其中有的设备只支持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>() {
- @Override
- public 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> {
- @Override
- protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
- //处理接收到的数据
- System.out.println("Received data ===>: " + msg.toString(StandardCharsets.UTF_8));
- }
-
- @Override
- public 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
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。