fuzhengwei / itstack-demo-netty

微信公众号:bugstack虫洞栈 | 专注于原创开发专题案例。跟着案例学Netty,Netty4.x案例从简单入门到应用实战,全篇37章节优秀案例+实战源码[基础篇(13)、中级篇(13)、高级篇(3章+)、源码分析篇],以上章节全部完成并不断持续更新中。欢迎关注公众号:bugstack虫洞栈 | 阅读专题文章+调试案例源码学习{回复netty案例}。
https://bugstack.cn
708 stars 359 forks source link

UDP 单播模式 #24

Open fuzhengwei opened 1 year ago

fuzhengwei commented 1 year ago

AnswerHandler

定义消息应答服务处理类,改类主要随机从字符串数组中选择一个发送给客户端

public class AnswerHandler extends
        SimpleChannelInboundHandler<DatagramPacket> {

    /*应答的具体内容从常量字符串数组中取得,由nextQuote方法随机获取*/
    private static final String[] DICTIONARY = {
            "测试消息"};
    private static Random r = new Random();
    private String nextQuote(){
        return DICTIONARY[r.nextInt(DICTIONARY.length-1)];
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx,
                                DatagramPacket packet)
            throws Exception {

        //获得请求
        String req = packet.content().toString(CharsetUtil.UTF_8);
        System.out.println("接收到请求:"+req);
        if(UdpQuestionSide.QUESTION.equals(req)){
            String answer = UdpAnswerSide.ANSWER+nextQuote();
            System.out.println("接收到请求:"+req);
            /**
             * 重新 new 一个DatagramPacket对象,我们通过packet.sender()来获取发送者的消息。重新发送出去!
             */
            ctx.writeAndFlush(
                    new DatagramPacket(
                            Unpooled.copiedBuffer(
                                    answer,
                                    CharsetUtil.UTF_8),
                            packet.sender()));
        }
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        ctx.close();
        cause.printStackTrace();
    }
}

UdpAnswerSide

定义应答服务器

 public final static String ANSWER = "笑话来了:";

    public void run(int port) throws Exception{
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            /*和tcp的不同,udp没有接受连接的说法,所以即使是接收端,
            也使用Bootstrap*/
            Bootstrap b = new Bootstrap();
            /*由于我们用的是UDP协议,所以要用NioDatagramChannel来创建*/
            b.group(group)
                .channel(NioDatagramChannel.class)
                .handler(new AnswerHandler());
            //没有接受客户端连接的过程,监听本地端口即可
            ChannelFuture f = b.bind(port).sync();
            System.out.println("应答服务已启动.....");
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully();
        }
    }
    public static void main(String [] args) throws Exception{
        int port = 7397;
        new UdpAnswerSide().run(port);
    }
复制代码

3、QuestoinHandler

定义应答服务器处理handler

public class QuestoinHandler extends
        SimpleChannelInboundHandler<DatagramPacket> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
            throws Exception {
        //获得应答,DatagramPacket提供了content()方法取得报文的实际内容
        String response = msg.content().toString(CharsetUtil.UTF_8);
        if (response.startsWith(UdpAnswerSide.ANSWER)) {
            System.out.println(response);
            ctx.close();
        }
    }

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

4、UdpQuestionSide

定义了一个请求客户端

public class UdpQuestionSide {

    public final static String QUESTION = "测试";

    public void run(int port) throws Exception{

        EventLoopGroup group  = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    /*由于我们用的是UDP协议,所以要用NioDatagramChannel来创建*/
                    .channel(NioDatagramChannel.class)
                    .handler(new QuestoinHandler());
            //不需要建立连接
            Channel ch = b.bind(0).sync().channel();
            //将UDP请求的报文以DatagramPacket打包发送给接受端
            ch.writeAndFlush(
                    new DatagramPacket(
                            Unpooled.copiedBuffer(QUESTION,
                                    CharsetUtil.UTF_8),
                            new InetSocketAddress("127.0.0.1",
                                    port)))
                    .sync();
            //不知道接收端能否收到报文,也不知道能否收到接收端的应答报文
            // 所以等待15秒后,不再等待,关闭通信
            if(!ch.closeFuture().await(15000)){
                System.out.println("查询超时!");
            }
        } catch (Exception e) {
            group.shutdownGracefully();
        }
    }
    public static void main(String [] args) throws Exception{
        int answerPort = 7397;

        new UdpQuestionSide().run(answerPort);
    }
}
theWaySoFar-arch commented 1 year ago

如果发送到多个不同的客户端,如何改进呢?