服务端给客户端推送消息用Netty+WS实现

# 前言

 

曾几何时,不知道大家有没有在项目里遇到过需要服务端给客户端推送消息的需求,是否曾经苦恼过、纠结过,我们知道要想实现这样的需求肯定离不开websocket长连接方式,那么到底是该选原生的websocket还是更加高级的netty框架呢?在此我极力推荐netty,因为一款好的框架一般都是在原生的基础上进行包装成更好、更方便、更实用的东西,很多我们需要自己考虑的问题都基本可以不用去考虑,不过此文不会去讲netty有多么的高深莫测,因为这些概念性的东西随处可见,而是通过实战来达到推送消息的目的。

 

# 实战

 

一、逻辑架构图

从图中可以看出本次实战的基本流程是客户端A请求服务端核心模块,核心模块生产一条消息到消息队列,然后服务端消息模块消费消息,消费完之后就将消息推送给客户端B,流程很简单,没有太多技巧,唯一的巧妙之处就在消息模块这边的处理上,本文的重点也主要讲解消息模块这一块,主要包括netty server、netty client、channel的存储等等。

 

二、代码

1、添加依赖

<dependency>
  <groupId>io.netty</groupId>
  <artifactId>netty-all</artifactId>
  <version>4.1.6.Final</version>
</dependency>

2、NettyServer类

@Service
public class NettyServer {
    public void run(int port){
        new Thread(){
            public void run(){
                runServer(port);
            }
        }.start();
    }

    private void runServer(int port){
        Print.info("===============Message服务端启动===============");
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup);
            b.channel(NioServerSocketChannel.class);
            b.childHandler(new ChannelInitializer<SocketChannel>() {
                protected void initChannel(SocketChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();
                    pipeline.addLast("codec-http", new HttpServerCodec());
                    pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
                    pipeline.addLast("handler", new MyWebSocketServerHandler());
                }
            });
            
            Channel ch = b.bind(port).sync().channel();
            Print.info("Message服务器启动成功:" + ch.toString());
            ch.closeFuture().sync();
        } catch (Exception e){
            Print.error("Message服务运行异常:" + e.getMessage());
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
            Print.info("Message服务已关闭");
        }
    }
}

3、MyWebSocketServerHandler类

public class MyWebSocketServerHandler extends SimpleChannelInboundHandler<Object>{
    private static final String WEBSOCKET_PATH = "";
    private WebSocketServerHandshaker handshaker;
  
    @Override    
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof FullHttpRequest){
            //以http请求形式接入,但是走的是websocket
            handleHttpRequest(ctx, (FullHttpRequest) msg);
        }else if (msg instanceof  WebSocketFrame){
            //处理websocket客户端的消息
            handleWebSocketFrame(ctx, (WebSocketFrame) msg);
        }
    }

    @Override    
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值