netty-udp客户端通信示例

 首先引入依赖

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

         <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.7.20</version>
        </dependency>
package com.bw.edgeagent.test;


import java.net.InetSocketAddress;

import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.ObjectUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
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;

/**
 * @Author mxf
 * @Description 客户端连接
 * @Date 2023/5/10 9:29 
 * @Param 
 * @return 
 **/
public class BootNettyUdpClient {

    public void bind(String address, int port, Object msg) {
        ByteBuf data = (ByteBuf) msg;
        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 BootNettyUdpHandler());

            Channel channel = clientBootstrap.bind(61005).sync().channel();

            //channel.writeAndFlush(new DatagramPacket(Unpooled.copiedBuffer(data, CharsetUtil.UTF_8), new InetSocketAddress(address,port))).sync();
            channel.writeAndFlush(new DatagramPacket(data, new InetSocketAddress(address,port))).sync();

            //  与BootNettyUdpClientSimpleChannelInboundHandler中的ctx.channel().id().toString()是一样的值
            System.out.println("channel_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");
        //String hexStr = "17 20 00 00 25 53 02 1B 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00";
        String hexStr = "17 80 00 00 25 53 02 1B 01 01 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00";
        ByteBuf byteBufMsg = getByteBuf(hexStr);
        // 指定某个套接字地址和发送的内容可以发送消息
        // 该方式也可以封装成一个udp的客户端的send类
        new BootNettyUdpClient().bind("10.1.77.180",60000,byteBufMsg);
    }


    /**
     * @return io.netty.buffer.ByteBuf
     * @Author Mxf
     * @Date 2022/4/15 11:57
     * @Description decodeHex 编码 艾礼安电子围栏主机服务端通过十六进制数据交互
     * @Param [command]
     **/
    private static ByteBuf getByteBuf(Object command) {
        String msg = ObjectUtil.toString(command);
        byte[] data = HexUtil.decodeHex(msg);
        ByteBuf byteBufMsg = Unpooled.buffer();
        byteBufMsg.writeBytes(data);
        return byteBufMsg;
    }
}
package com.bw.edgeagent.test;

import cn.hutool.core.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.socket.DatagramPacket;
import io.netty.util.CharsetUtil;

/**
 * @Author mxf
 * @Description 消息处理类 
 * @Date 2023/5/10 9:30 
 * @Param 
 * @return 
 **/
public class BootNettyUdpHandler 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("msg1111111111---"+ strData);
            //打印收到的消息
            System.out.println("msg222222222---"+ getHexString(msg.content()));
            // 与BootNettyUdpClient中的channel.id().toString()是一样的值
            System.out.println(ctx.channel().id().toString());
            //	收到服务端原路返回的消息后,不需要再次向服务端发送消息, 可以在这里暴力关闭,也可以在 channelReadComplete(ChannelHandlerContext ctx)内
            //  ctx.close();
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    /**
     * @return java.lang.String
     * @Author Mxf
     * @Date 2022/4/15 11:54
     * @Description 艾礼安电子围栏返回的是十六进制数据 解码 十六进制数据转成字符串
     * @Param [msg]
     **/
    private String getHexString(Object msg) {
        ByteBuf buf = (ByteBuf) msg;
        byte[] con = new byte[buf.readableBytes()];
        buf.readBytes(con);
        return HexUtil.encodeHexStr(con);
    }

    /**
     * 	重写方法
     * 	结构:
     * 	1.public class BootNettyUdpHandler 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();
    }

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值