netty udp创建服务端+客户端

一.udp创建服务端

复制代码
/**
 * udp 服务器 
 */
@Slf4j
@Component
public class UdpServer {
    /**
     * 创建服务端
     */
    @Async
    public void bind(int port) {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))
                    .handler(new ChannelInitializer<DatagramChannel>() {
                        @Override
                        public void initChannel(DatagramChannel ch) {
                            ChannelPipeline cp = ch.pipeline();
                            cp.addLast(new ServerHandler(port));
                        }
                    });
            Channel serverChannel = b.bind(port).sync().channel();
            log.info("UdpServer start success...");
            serverChannel.closeFuture().await();
        } catch (Exception e) {
            log.error("UdpServer start fall!");
        } finally {
            group.shutdownGracefully();
        }

    }

    private class ServerHandler extends SimpleChannelInboundHandler<DatagramPacket> {

        private int port;// 当前 端口

        public ServerHandler(int port) {
            this.port = port;
        }

        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            log.error(cause.getMessage());
            cause.printStackTrace();
        }

        /**
         * 接收消息
         */
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet) {
            // 1.获取数据内容,它是一个ByteBuf
            ByteBuf content = packet.content();
 			String request = content.toString(CharsetUtil.UTF_8);

            // 2.你可以使用ByteBuf的API来读取数据
            //byte[] bytes = new byte[content.readableBytes()];
            //content.readBytes(bytes);
            //String request = new String(bytes, StandardCharsets.UTF_8);

            InetSocketAddress senderAddress = packet.sender();
            log.info("{} ---> {}:{}", senderAddress.getAddress().getHostAddress(), this.port, request);
           
        }
    }

}

二.udp创建客户端

下面展示一些 有些地方赖得改了,当是记录

复制代码
@Slf4j
@Component
public class UdpClient {
  
    /**
     * 发送udp,等待对方回复
     *
     * @param ip
     * @param port
     * @param format str,hex
     * @param msg
     * @return
     */
    public String sendData(String ip, int port, String format, Object msg) {
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
        EventLoopGroup group = new NioEventLoopGroup();
        Channel channel = null;
        Response r = new Response();
        try {
            InetSocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getByName(ip), port);
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioDatagramChannel.class)
                    .handler(new SimpleChannelInboundHandler() {
                        @Override
                        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                            log.error("exceptionCaught ->" + cause.getMessage());
                            cause.printStackTrace();
                            ctx.close();
                        }

                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                            // 处理接收到的数据
                            ByteBuf byteBuf = ((DatagramPacket)msg).content();
                            String response = null;
                            if (format.equals("str")) {
                                response = byteBuf.toString(StandardCharsets.UTF_8);
                            } else {
                                response = ByteBufUtil.hexDump(byteBuf);
                            }
                            log.info("response msg: " + response);
                            r.setMsg(response);
                            ctx.close();
                        }

                    });
            ChannelFuture future = b.bind(0).sync(); // 绑定端口0以获取随机可用端口
            channel = future.channel();
            log.info("{}  <- {}", ip, msg.toString());
            Channel finalChannel = channel;
            Future<?> executorServiceFuture = executorService.schedule(() -> {
                // 检查Channel是否仍然是活动状态
                if (finalChannel.isActive()) {
                    finalChannel.close();
                }
            }, 35, TimeUnit.SECONDS);
            ByteBuf byteBuf = null;
            if (format.equals("str")) {
                byteBuf = Unpooled.copiedBuffer(msg.toString(), CharsetUtil.UTF_8); // 将消息内容转换为ByteBuf
            } else {
                byte[] bytes = hexString2Bytes(msg.toString());// 将16进制字符串转换为字节数组
                byteBuf = Unpooled.wrappedBuffer(bytes); // 使用字节数组创建ByteBuf
            }
            DatagramPacket requestPacket = new DatagramPacket(byteBuf, inetSocketAddress);
            channel.writeAndFlush(requestPacket);// 发送
            channel.closeFuture().await();//异步等待,通道关闭后会往下执行
            executorServiceFuture.cancel(true); // 立刻中断
            return r.getMsg();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        } finally {
            executorService.shutdown(); // 清理资源
            if (channel != null) channel.close();
            group.shutdownGracefully();
        }
    }

    /**
     * 发送udp,不等待回复
     * @param ip
     * @param port
     * @param msg
     */
    public void sendDataNoReply(String ip, int port, Object msg) {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioDatagramChannel.class)
                    .option(ChannelOption.SO_BROADCAST, true)
                    .handler(new SimpleChannelInboundHandler() {
                        @Override
                        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
                            cause.printStackTrace();
                            ctx.close();
                        }
                        @Override
                        protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                            // 处理接收到的数据
                        }
                    });
            Channel channel = bootstrap.bind(0).sync().channel();
            // 发送数据到指定的地址和端口
            InetSocketAddress address = new InetSocketAddress(ip, port);
            ByteBuf buffer = Unpooled.copiedBuffer(msg.toString(), CharsetUtil.UTF_8);
            DatagramPacket packet = new DatagramPacket(buffer, address);
            channel.writeAndFlush(packet);

            // 等待一段时间以确保数据发送完成
            //Thread.sleep(1000);
        } catch (InterruptedException e) {
            log.error("发送udp数据失败:", e);
            throw new RuntimeException("发送数据失败或连接不上");
        } finally {
            group.shutdownGracefully();
        }
    }


    class Response {
        private String msg;

        public Response() {
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    public static byte[] hexString2Bytes(String src) {
        byte[] bytes = new byte[src.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            int index = i * 2;
            int j = Integer.parseInt(src.substring(index, index + 2), 16);
            bytes[i] = (byte) j;
        }
        return bytes;
    }

}
相关推荐
SimonKing2 分钟前
手机投屏到电脑,不用装任何 App,这个开源工具免费搞定:QtScrcpy
java·后端·程序员
ouynagda9 分钟前
Linux Socket 网络编程学习笔记
linux·网络·学习
学长毕业设计10 分钟前
基于SpringBoot的奶茶店服务管理系统的设计与实现(源码+文档+讲解视频)
java·spring boot·后端
牛马也想出海11 分钟前
海外社媒代理IP:TikTok、IG等6大社媒平台防封号IP选型指南
运维·服务器·网络·新媒体运营
蛋先生DX14 分钟前
明明都是源码到CPU,各语言中间原理咋不是一个套路?
java·javascript·go
昌原的儿子LEO17 分钟前
【Linux网络编程】TCP套接字核心函数详解|三次握手|send/recv/listen/accept接口梳理
linux·网络·tcp/ip
我爱cope18 分钟前
【计算机网络 | 网络层12:SDN:控制平面与数据平面分离意味着什么?】
网络·学习·计算机网络·平面
萧瑟余晖19 分钟前
Java深入解析篇十三之Java日志API(JUL)详解
java·开发语言
阿崽meitoufa20 分钟前
Prompt Engineering for Agent:让 Agent 稳定运行的提示词写法
网络·人工智能·microsoft
筝筝ba23 分钟前
extended/factory_reset.robot
linux·运维·服务器·网络·网络协议·p2p