ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Springboot+Netty搭建基于UDP协议的客户端(四)

2022-06-17 18:36:14  阅读:150  来源: 互联网

标签:Netty UDP Springboot netty ctx 服务端 io import channel


使用Netty+SpringBoot方式可以快速地开发一套基于UDP协议的服务端程序,同样的也可以开发客户端,一般使用UDP都是使用原生的方式,发送消息后就不管不问,也就是不需要确定消息是否收到,这里使用Netty创建的客户端和服务端倒是能够类似http协议那样请求数据,得到返回数据,实际上得到的就是服务端原路返回的数据。


1、这里也使用SpringBoot+Netty创建,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、Netty客户端的类,包含main方法,这里就没有使用SpringBoot方式的启动

package boot.netty.udp.client;


import java.net.InetSocketAddress;
import boot.netty.udp.client.adapter.BootNettyUdpClientSimpleChannelInboundHandler;
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;

public class BootNettyUdpClient {

	public void bind(String address, int port, String data) {

		EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
		try {
            Bootstrap clientBootstrap = new Bootstrap();
            clientBootstrap = clientBootstrap.group(eventLoopGroup);
            clientBootstrap = clientBootstrap.channel(NioDatagramChannel.class);
            clientBootstrap = clientBootstrap.option(ChannelOption.SO_BROADCAST, true);
            clientBootstrap = clientBootstrap.handler(new BootNettyUdpClientSimpleChannelInboundHandler());

            Channel channel = clientBootstrap.bind(0).sync().channel();
            channel.writeAndFlush(new DatagramPacket(
                Unpooled.copiedBuffer(data, CharsetUtil.UTF_8),
                new InetSocketAddress(address,port))).sync();

            //  与BootNettyUdpClientSimpleChannelInboundHandler中的ctx.channel().id().toString()是一样的值
            System.out.println("channnel id = "+channel.id().toString());

            //  方式一:查询等待超时 单位s  等待服务端原路返回的消息,
            //  在channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)方法中
            //  收到消息后可主动关闭channel,此处等待自然释放  
            channel.closeFuture().await(10000);

            //	方式二:直接等待服务端原路返回后在channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)方法中
            //  收到消息后可主动关闭channe
            //  若服务端没有原路返回消息或者消息未收到将会一直等待,浪费资源
            //channel.closeFuture().sync();

		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			System.out.println("netty client udp close!");
			eventLoopGroup.shutdownGracefully();
		}
	}



	public static void main(String[] args) {

		//  向网段内的所有机器广播UDP消息,这个没试过是不是这个原理
		// new BootNettyUdpClient().bind("255.255.255.255",9999,"I am client");

		// 指定某个套接字地址和发送的内容可以发送消息
		// 该方式也可以封装成一个udp的客户端的send类
		new BootNettyUdpClient().bind("127.0.0.1",9999,"I am client");


	}

}

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

package boot.netty.udp.client.adapter;


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

public class BootNettyUdpClientSimpleChannelInboundHandler 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);
            // 与BootNettyUdpClient中的channel.id().toString()是一样的值
            System.out.println(ctx.channel().id().toString());
            //	收到服务端原路返回的消息后,不需要再次向服务端发送消息, 可以在这里暴力关闭,也可以在 channelReadComplete(ChannelHandlerContext ctx)内
            //  ctx.close();
		} catch (Exception e) {

		}
	}

	/**
	 * 	重写方法
	 * 	结构:
	 * 	1.public class BootNettyUdpClientSimpleChannelInboundHandler extends SimpleChannelInboundHandler<DatagramPacket>
	 *
	 * 	2.public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter
	 *
	 * 	3.public class ChannelInboundHandlerAdapter extends ChannelHandlerAdapter implements ChannelInboundHandler
	 *
	 * 	ChannelInboundHandlerAdapter类有诸多方法可以重写,可以根据具体需求来写
	 *
	 */

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		super.channelReadComplete(ctx);
		System.out.println("关闭channel");
		ctx.close();
	}

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}

4、我们可以启动一个服务端(SpringBoot搭建基于UDP协议的服务端)然后调用main方法,可以看到服务端可以收到消息,客户端也可以收到服务端原路返回的时间戳消息

	public static void main(String[] args) {

		//  向网段内的所有机器广播UDP消息,这个没试过是不是这个原理
		// new BootNettyUdpClient().bind("255.255.255.255",9999,"I am client");

		// 指定某个套接字地址和发送的内容可以发送消息
		// 该方式也可以封装成一个udp的客户端的send类
		new BootNettyUdpClient().bind("127.0.0.1",9999,"I am client");


	}


标签:Netty,UDP,Springboot,netty,ctx,服务端,io,import,channel
来源: https://www.cnblogs.com/haolb123/p/16386736.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有