• Springboot+Netty搭建基于UDP协议的服务端(三)


      UDP是一个无连接协议,应用范围很大,对于一些低功耗的设备可以使用UDP方式向云端推送消息信息,也可以在推送消息时收到从云端原路返回的消息,使用Netty+SpringBoot方式可以快速开发一套基于UDP协议的服务端程序。

    1、 新建Springboot的maven项目,pom.xml文件导入依赖包

    ​
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>2.1.6.RELEASE</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    
    	<dependencies>
    
    		<!--web模块的启动器 -->
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    		<!-- netty依赖 springboot2.x自动导入版本 -->
    		<dependency>
    			<groupId>io.netty</groupId>
    			<artifactId>netty-all</artifactId>
    		</dependency>
    
    	</dependencies>

    ​2、Springboot启动类,使用异步方式启动一个基于UDP协议的Netty应用(也包含web应用的)

    package boot.netty.udp;
    
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.scheduling.annotation.Async;
    import org.springframework.scheduling.annotation.EnableAsync;
    
    
    @SpringBootApplication
    @EnableAsync
    public class BootNettyUdpApplication implements CommandLineRunner{
        public static void main( String[] args )
        {
        	/**
        	 * 启动springboot
        	 */
    		SpringApplication app = new SpringApplication(BootNettyUdpApplication.class);
    		app.run(args);
    
            System.out.println( "Hello World!" );
        }
    
        @Async
    	@Override
    	public void run(String... args) throws Exception {
    		/**
    		 * 使用异步注解方式启动netty udp服务端服务
    		 */
    		new BootNettyUdpServer().bind(9999);
    
    	}
    }

    3、Netty的UDP启动类

    package boot.netty.udp;
    
    import boot.netty.udp.adapter.BootNettyUdpSimpleChannelInboundHandler;
    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;
    
    public class BootNettyUdpServer {
    
    	/**
    	 * 启动服务
    	 */
    	public void bind(int port) {
    
    		EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
    		try {
    			//UDP方式使用Bootstrap
                Bootstrap serverBootstrap = new Bootstrap();
                serverBootstrap = serverBootstrap.group(eventLoopGroup);
                serverBootstrap = serverBootstrap.channel(NioDatagramChannel.class);
                serverBootstrap = serverBootstrap.option(ChannelOption.SO_BROADCAST, true);
                //不需要太多其他的东西,直接这样就可以用
                serverBootstrap = serverBootstrap.handler(new BootNettyUdpSimpleChannelInboundHandler());
                System.out.println("netty udp start!");
                ChannelFuture f = serverBootstrap.bind(port).sync();
                f.channel().closeFuture().sync();
    		} catch (Exception e) {
    			// TODO: handle exception
    		} finally {
    			System.out.println("netty udp close!");
    			eventLoopGroup.shutdownGracefully();
    		}
    	}
    }

    4、服务端I/O数据读写处理类

    package boot.netty.udp.adapter;
    
    
    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;
    
    public class BootNettyUdpSimpleChannelInboundHandler extends SimpleChannelInboundHandler<DatagramPacket> {
    
    	@Override
    	protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) throws Exception {
    		try {
    			String strdata = msg.content().toString(CharsetUtil.UTF_8);
    			//打印收到的消息
                System.out.println("msg---"+strdata);
    			//收到udp消息后,可通过此方式原路返回的方式返回消息,例如返回时间戳
                ctx.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(System.currentTimeMillis()/1000+"", CharsetUtil.UTF_8), msg.sender()));
            } catch (Exception e) {
    
    		}
    	}
    
    }

    可以使用一些UDP客户端的软件来测试,这个Demo应用是基于Netty4.x的,对于Netty5.0有一些小的变化,在I/O数据处理类这里的变化需要注意,channelRead0(ChannelHandlerContext, I)方法改成了messageReceived(ChannelHandlerContext, I)},否则代码会报错然后找不到原因,Netty方法源码上是有注释信息的。

  • 相关阅读:
    Java高并发专题之34、谷歌提供的一些好用的并发工具类
    Java高并发专题之31、等待线程完成的方式你知道几种?
    Java高并发专题之27、实战:你的接口太慢了需要优化
    Java高并发专题之36、线程6种状态详解
    Java高并发专题之32、原子操作增强类LongAdder、LongAccumulator
    Java高并发专题之35、延迟队列 DelayQueue 详解
    Java高并发专题之29、实战:一起来搞懂限流
    Java高并发专题之33、怎么演示公平锁和非公平锁
    Java高并发专题之30、JUC中的CompletableFuture
    plugin:prettier/recommended和vue/maxattributesperline冲突
  • 原文地址:https://www.cnblogs.com/haolb123/p/16553004.html
Copyright © 2020-2023  润新知