Java使用webflux实现udp服务对接Modbus的udp协议

通过 webflux,你可以快速搭建一个基于Reactor Netty或其他反应式运行时(如Tomcat, Jetty)的Web应用,并利用Spring Framework提供的全套功能,包括路由处理、数据绑定、验证、模板引擎等。 

1、引入Jar包

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
    <!-- Reactor Netty for UDP support -->
    <dependency>
        <groupId>io.projectreactor.netty</groupId>
        <artifactId>reactor-netty</artifactId>
    </dependency>
</dependencies>

2、实现UDP服务配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.netty.DisposableServer;
import reactor.netty.udp.UdpServer;
import java.time.Duration;
import java.util.function.Consumer;

@Configuration
public class UdpServerConfig {

    //你的ip和port
    private final String host = "localhost";
    private final int port = 9000;
    // 自定义了这个解码器
    private final UdpDecoderHandler udpDecoderHandler = new UdpDecoderHandler(); 
    @Bean
    public DisposableServer udpServer() {
        return UdpServer.create()
                .host(host)
                .port(port)
                .handle((in, out) -> in.receive()
                        .asByteArray()
                        .doOnNext(data -> handleUdpData(data)) // 处理接收到的数据
                        .then()) // 完成流后关闭连接(对于UDP来说通常不需要)
                .doOnBound(conn -> conn.addHandlerLast("decoder", udpDecoderHandler))
                .bindNow(Duration.ofSeconds(30));
    }

    private void handleUdpData(byte[] data) {
        // 在这里处理你的UDP数据
        System.out.println("Received UDP data: " + new String(data));
    }
}

3、自定义解码器 

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.util.ReferenceCountUtil;
import reactor.core.publisher.Flux;
import java.net.InetSocketAddress;
import java.util.List;

public class UdpDecoderHandler extends MessageToMessageDecoder<DatagramPacket> {

    // 解码器实现,继承自MessageToMessageDecoder<DatagramPacket>
    @Override
    protected void decode(ChannelHandlerContext ctx, DatagramPacket datagramPacket, List<Object> out) throws Exception {
        // 获取DatagramPacket中的ByteBuf数据部分,不进行复制以提高性能
        ByteBuf content = datagramPacket.content();

        // 创建一个新的自定义对象,包含原始数据和源地址信息
        CustomUdpMessage message = new CustomUdpMessage(content.copy(), datagramPacket.sender());

        // 将解码后的消息添加到输出列表中,供后续处理器使用
        out.add(message);

        // 释放原始的DatagramPacket资源,防止内存泄漏
        ReferenceCountUtil.release(datagramPacket);
    }

    // 自定义UDP消息类,包含原始数据和发送者的地址信息
    public static class CustomUdpMessage {
        private final ByteBuf data; // 使用ByteBuf而不是字节数组,避免不必要的数据复制
        private final InetSocketAddress sender;

        // 构造函数,将ByteBuf内容和发送者地址保存为实例变量
        public CustomUdpMessage(ByteBuf data, InetSocketAddress sender) {
            this.data = data;
            this.sender = sender;
        }

        // 提供获取数据的方法,但通常在处理时直接操作ByteBuf会更高效
        public ByteBuf getData() {
            return data;
        }

        // 获取发送者地址
        public InetSocketAddress getSender() {
            return sender;
        }
        
        // 在完成对CustomUdpMessage的处理后,记得释放其中包含的ByteBuf资源
        public void releaseData() {
            data.release();
        }
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值