一个群聊的netty 例子

栏目: 编程工具 · 发布时间: 5年前

内容简介:翻了翻《Netty 实战》,看了些概念,还是觉得似是而非,于是写了些代码,通道啥的都建得挺好。但是channelRead0一直收不到消息。后来东摸西摸,发现我client 创建channel后马上发消息是不对的,此时channel还没有完全建好,导致服务端收不到消息。改成通道active后,server 给 client发送消息,client 收到消息后才开始向server发消息,此时sever是能收到的。

翻了翻《Netty 实战》,看了些概念,还是觉得似是而非,于是写了些代码,通道啥的都建得挺好。但是channelRead0一直收不到消息。

后来东摸西摸,发现我client 创建channel后马上发消息是不对的,此时channel还没有完全建好,导致服务端收不到消息。改成通道active后,server 给 client发送消息,client 收到消息后才开始向server发消息,此时sever是能收到的。

实现Server handler

@Slf4j
public class ChatServerHandler extends SimpleChannelInboundHandler<String> {

    public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        // 处理handler 添加,全局保存channel
        log.info("add a handler");
        Channel incoming = ctx.channel();
        for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n");
        }
        channels.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        // 处理handler 删除,全局删除channel
        Channel incoming = ctx.channel();
        for (Channel channel : channels) {
            channel.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n");
        }
        channels.remove(ctx.channel());
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel incoming = ctx.channel();

        log.info("收到消息: " + msg);
        for (Channel channel : channels) {
            if (channel != incoming) {
                // 群发给其他用户
                channel.writeAndFlush("[" + incoming.remoteAddress() + "]" + msg + "\n");
            } else {
                // 回应当前用户
                channel.writeAndFlush("[响应]" + msg + "\n");
            }
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        // 通道激活,通知client,可以准备通信了
        Channel incoming = ctx.channel();
        log.info("ChatClient:" + incoming.remoteAddress() + "在线");
        incoming.writeAndFlush("welcome" + "\n");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 通道失效,client 掉线
        Channel incoming = ctx.channel();
        log.info("ChatClient:" + incoming.remoteAddress() + "掉线");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception 
    {
        Channel incoming = ctx.channel();

        // 当出现异常就关闭连接
        log.info("ChatClient:" + incoming.remoteAddress() + "异常");
        cause.printStackTrace();
        ctx.close();
    }
}

服务端通过引导绑定IP

ServerBootstrap serverBootstrap = new ServerBootstrap();

        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        serverBootstrap
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel ch) throws Exception 
                            {
                                ChannelPipeline pipeline = ch.pipeline();
                                pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
                                pipeline.addLast("decoder", new StringDecoder());
                                pipeline.addLast("encoder", new StringEncoder());
                                pipeline.addLast("handler", new ChatServerHandler());
                                log.info("ChatClient:" + ch.remoteAddress() + "连接上");
                            }
                        }
                ).option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .bind(18169);

实现 client handler

@Slf4j
public class ChatClientHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        log.info(msg);
        Channel ch = ctx.channel();
        
        // 收到welcome后,给server发送消息
        if(msg.startsWith("welcome")){
            ch.writeAndFlush("hello world!" + "\r\n");
            ch.writeAndFlush("wish you happy!" + "\r\n");
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception 
    {
        cause.printStackTrace();
        //        出现异常时关闭连接
        ctx.close();
    }
}

通过引导创建 client channel

Bootstrap bootstrap = new Bootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();

        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(
                        new ChannelInitializer<NioSocketChannel>() {
                            @Override
                            protected void initChannel(NioSocketChannel ch) throws Exception 
                            {
                                ChannelPipeline pipeline = ch.pipeline();
                                // 解决粘包问题
                                pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
                                pipeline.addLast("decoder", new StringDecoder());
                                pipeline.addLast("encoder", new StringEncoder());
                                pipeline.addLast("handler", new ChatClientHandler());
//                                log.info("ChatServer:" + ch.remoteAddress() + "连接上");
                            }
                        }
                ).option(ChannelOption.SO_KEEPALIVE, true);

        Channel channel = bootstrap.connect("127.0.0.1", 18169).channel();

    }

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

HTML网页设计参考手册

HTML网页设计参考手册

张金霞 / 清华大学 / 2006-9 / 39.00元

本书由最基本的HTML语法开始讲解网页设计的基础技术,详细介绍了各种网页制作的标记;然后介绍如何运用CSS控制网页画面中文字与图片的样式;接下来讲解了JavaScript语言与网页特效的制作;最后以应用最广泛的Drcamweaver为例,介绍网页设计的方法。在讲解中配有大量范例,使读者在实际操作中学习制作网页。   HTML语言是制作网页的基础语言。作为一个网页制作爱好者或者专业的网......一起来看看 《HTML网页设计参考手册》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

随机密码生成器
随机密码生成器

多种字符组合密码