netty 实现消息群发

主程序启动模版

package net.jlxxw.wechat.temp;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import net.jlxxw.wechat.component.netty.WeChatCoreComponent;
import net.jlxxw.wechat.util.LoggerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author chunyang.leng
 * @date 2022-04-27 9:35 AM
 */
public class Main {
    private static final ServerBootstrap BOOTSTRAP = new ServerBootstrap();
    private static final Logger logger = LoggerFactory.getLogger(WeChatCoreComponent.class);
    

    public static void main(String[] args) {

        LoggerUtils.info(logger, "初始化 netty 组件");
        //new 一个主线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //new 一个工作线程组
        EventLoopGroup workGroup = new NioEventLoopGroup(200);
        BOOTSTRAP
                .group(bossGroup, workGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        // todo 编解码器 略

                        socketChannel.pipeline().addLast("channel_manager",new AllChannelManager());
                        // 自定义处理handler
                        socketChannel.pipeline().addLast("chatChannel", new ChatChannel());
                        LoggerUtils.debug(logger, "初始化 netty 微信协议处理器 成功");
                    }
                })
                .localAddress(9999)
                //设置队列大小
                .option(ChannelOption.SO_BACKLOG, 200)
                // 不保持长链接
                .childOption(ChannelOption.SO_KEEPALIVE, false);
        //绑定端口,开始接收进来的连接
        try {
            ChannelFuture future = BOOTSTRAP.bind(9999).sync();
            LoggerUtils.info(logger, "netty服务启动,开始监听端口: {}", 9999);
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            LoggerUtils.error(logger, "netty服务启动失败!!!", e);
            System.exit(0);
        } finally {
            //关闭主线程组
            bossGroup.shutdownGracefully();
            //关闭工作线程组
            workGroup.shutdownGracefully();
        }
    }

}

业务处理channel

package net.jlxxw.wechat.temp;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.jlxxw.wechat.util.LoggerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;

/**
 * netty回调处理接口
 *
 * @author chunyang.leng
 * @date 2021/1/25 9:46 上午
 */
@Component
@ChannelHandler.Sharable
public class ChatChannel extends SimpleChannelInboundHandler<ByteBuf> {
    private static final Logger logger = LoggerFactory.getLogger(ChatChannel.class);

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
        LoggerUtils.debug(logger, "netty 开始处理");

        // 请求体数据转byte数组
        byte[] reqContent = new byte[byteBuf.readableBytes()];
        // 缓存数据加载至byte数组中
        byteBuf.readBytes(reqContent);

        final String requestData = new String(reqContent, StandardCharsets.UTF_8);
        logger.info("接收到请求数据:{}",requestData);
        AllChannelManager.sendAll(requestData);
    }

    /**
     * 异常信息记录
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        // 记录异常日志
        LoggerUtils.error(logger,"netty-thread 发生未知异常",cause);
        // 关闭异常连接
        ctx.close();
    }
}

channel管理器

package net.jlxxw.wechat.temp;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.ImmediateEventExecutor;

/**
 * @author chunyang.leng
 * @date 2022-04-27 9:41 AM
 */
public class AllChannelManager extends ChannelDuplexHandler {
    /**
     * ChannelGroup用来保存所有已经连接的Channel
     */
    private final static ChannelGroup CHANNEL_GROUP = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        CHANNEL_GROUP.add(ctx.channel());
        super.channelActive(ctx);
    }


    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        CHANNEL_GROUP.remove(ctx.channel());
        super.channelInactive(ctx);
    }

    /**
     * 发送给所有人
     * @param message
     */
    public static void sendAll(String message){
        CHANNEL_GROUP
                .parallelStream()
                .filter(Channel::isActive)
                .forEach(channel -> {
                    ByteBuf byteBuf = Unpooled.directBuffer(message.length());
                    byteBuf.writeCharSequence(message, CharsetUtil.UTF_8);
                    channel.writeAndFlush(byteBuf);
                });
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北漂的菜小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值