springboot整合netty开发udp网关

1. 添加maven关联依赖包

<dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--Kafka依赖包-->
        <dependency>
            <groupId>org.springframework.kafka</groupId>
            <artifactId>spring-kafka</artifactId>
        </dependency>


        <dependency>
            <groupId>org.apache.kafka</groupId>
            <artifactId>kafka_2.12</artifactId>
            <version>2.3.0</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>

        <!-- netty依赖 -->
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
<!--            <version>4.1.51.Final</version>-->
        </dependency>

    </dependencies>

2. 编写springboot启动类

package com.hnu;

import com.hnu.server.UdpServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.scheduling.annotation.Async;

/**
 * @description:
 * @author: YUANHX
 * @create: 1:56 下午
 **/
@SpringBootApplication
@EnableDiscoveryClient
public class UdpApplication implements CommandLineRunner {

    private static final Logger LOGGER = LoggerFactory.getLogger(UdpApplication.class);

    @Autowired
    private UdpServer udpServer;

    public static void main(String[] args) {
        SpringApplication app = new SpringApplication(UdpApplication.class);
        LOGGER.info("udp server starting.........................");
        app.run(args);

    }

    @Async
    @Override
    public void run(String... args) throws Exception {
        /**
         * 使用异步注解方式启动netty udp服务端服务
         */
        udpServer.bind();
    }
}

3. 编写服务端代码

package com.hnu.server;

import com.hnu.handler.UdpSimpleChannelInboundHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @description: UDPserver
 * @author: YUANHX
 * @create: 1:58 下午
 **/
@Component
public class UdpServer {

    private static final Logger LOGGER = LoggerFactory.getLogger(UdpServer.class);

    /** netty udp port**/
    @Value("${netty.udp.port}")
    private int port;

    public void bind(){
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try{
            // UDP方式使用BootStrap
            Bootstrap serverBootStrap = new Bootstrap();
            serverBootStrap.group(eventLoopGroup)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST,true)
                    .handler(new UdpSimpleChannelInboundHandler());
            LOGGER.info("udp server start!....................");
            ChannelFuture future = serverBootStrap.bind(port).sync();
            future.channel().closeFuture().sync();
        }catch (Exception e){
            LOGGER.error("udp server start error;{}", e);
        }finally {
            LOGGER.info("udp server close!..................");
            eventLoopGroup.shutdownGracefully();
        }

    }
}
package com.hnu.server.handler;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @description: 服务端I/O数据读写处理类
 * @author: YUANHX
 * @create: 2:24 下午
 **/
public class UdpSimpleChannelInboundHandler extends SimpleChannelInboundHandler<DatagramPacket> {

    private static final Logger LOGGER = LoggerFactory.getLogger(UdpSimpleChannelInboundHandler.class);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
        try{
/*

            //做类型转换,将msg转换成Netty的ByteBuf对象。
            //ByteBuf类似于JDK中的java.nio.ByteBuffer 对象,不过它提供了更加强大和灵活的功能。
            ByteBuf buf = packet.copy().content();

            //通过ByteBuf的readableBytes方法可以获取缓冲区可读的字节数,
            //根据可读的字节数创建byte数组
            byte[] req = new byte[buf.readableBytes()];
            //通过ByteBuf的readBytes方法将缓冲区中的字节数组复制到新建的byte数组中
            buf.readBytes(req);
            //通过new String构造函数获取请求消息。
            String body = HexStringUtils.bytesToHexString(req).toUpperCase();
            System.out.println(body);//打印收到的信息
            //向客户端发送消息
            String json = "hello world!!";
            // 由于数据报的数据是以字符数组传的形式存储的,所以传转数据
            byte[] bytes = json.getBytes("UTF-8");
            DatagramPacket data = new DatagramPacket(Unpooled.copiedBuffer(bytes), packet.sender());
            channelHandlerContext.writeAndFlush(data);//向客户端发送消息
*/


            String str = packet.content().toString(CharsetUtil.UTF_8);
            // 打印收到的消息
            LOGGER.info("udp server recieve message:{}", str);
            //收到udp消息后,可通过此方式原路返回的方式返回消息,例如返回时间戳
            channelHandlerContext.writeAndFlush(
                    new DatagramPacket(
                            Unpooled.copiedBuffer(System.currentTimeMillis()/1000 +"", CharsetUtil.UTF_8),
                            packet.sender()
                    )
            );
        }catch (Exception e){
            LOGGER.error("udp server recieve message error:{}", e);
        }finally {
//            channelHandlerContext.close();
        }

    }
}

4. 编写客户端代码

package com.hnu.client;

import com.hnu.client.handler.UdpClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;

import java.net.InetSocketAddress;

/**
 * @description: udp client
 * @author: YUANHX
 * @create: 2:48 下午
 **/
public class UdpClient {

    public static void main(String[] args) throws Exception{
        int port = 8301;
        if(args != null && args.length > 0){
            port = Integer.valueOf(args[0]);
        }
        new UdpClient().run(port);
    }

    public void run(int port) throws Exception{
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        try {

            bootstrap.group(eventLoopGroup)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(new UdpClientHandler());

            Channel channel = bootstrap.bind(0).sync().channel();
            //向网段内所有机器广播
            channel.writeAndFlush(
                    new DatagramPacket(
                            Unpooled.copiedBuffer("发个测试信息", CharsetUtil.UTF_8),
//                            new InetSocketAddress("255.255.255.255", port)
                            new InetSocketAddress("192.168.3.9", port)
                    )
            ).sync();

            //客户端等待15s用于接收服务端的应答消息,然后退出并释放资源
            if(!channel.closeFuture().await(15000L)){
                System.out.println("查询超时!");
            }

        }catch (Exception e){
            e.printStackTrace();
        }finally {
            eventLoopGroup.shutdownGracefully();
        }


    }
}
package com.hnu.client.handler;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;


/**
 * @description:
 * @author: YUANHX
 * @create: 3:04 下午
 **/
public class UdpClientHandler extends SimpleChannelInboundHandler<DatagramPacket> {
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, DatagramPacket packet) throws Exception {
        String resp = packet.content().toString(CharsetUtil.UTF_8);
        System.out.println("客户端接收结果:"+resp);
        channelHandlerContext.close();

    }
}

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一一可可

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值