0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Netty如何实现消息推送

Android编程精选 来源:Android编程精选 作者:Android编程精选 2022-08-30 09:42 次阅读

Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。

Maven依赖


   io.netty netty-all 4.1.36.Final  

SpringBootApplication

启动器中需要new一个NettyServer,并显式调用启动netty。


@SpringBootApplication publicclassSpringCloudStudyDemoApplication{ publicstaticvoidmain(String[]args){ SpringApplication.run(SpringCloudStudyDemoApplication.class,args); try{ newNettyServer(12345).start(); System.out.println("https://blog.csdn.net/moshowgame"); System.out.println("http://127.0.0.1:6688/netty-websocket/index"); }catch(Exceptione){ System.out.println("NettyServerError:"+e.getMessage()); } } }

NettyServer

启动的NettyServer,这里进行配置


/** *NettyServerNetty服务器配置 *@authorzhengkai.blog.csdn.net *@date2019-06-12 */ publicclassNettyServer{ privatefinalintport;  publicNettyServer(intport){ this.port=port; }  publicvoidstart()throwsException{ EventLoopGroupbossGroup=newNioEventLoopGroup();  EventLoopGroupgroup=newNioEventLoopGroup(); try{ ServerBootstrapsb=newServerBootstrap(); sb.option(ChannelOption.SO_BACKLOG,1024); sb.group(group,bossGroup)//绑定线程池 .channel(NioServerSocketChannel.class)//指定使用的channel .localAddress(this.port)//绑定监听端口 .childHandler(newChannelInitializer(){//绑定客户端连接时候触发操作  @Override protectedvoidinitChannel(SocketChannelch)throwsException{ System.out.println("收到新连接"); //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 ch.pipeline().addLast(newHttpServerCodec()); //以块的方式来写的处理器 ch.pipeline().addLast(newChunkedWriteHandler()); ch.pipeline().addLast(newHttpObjectAggregator(8192)); ch.pipeline().addLast(newWebSocketServerProtocolHandler("/ws",null,true,65536*10)); ch.pipeline().addLast(newMyWebSocketHandler()); } }); ChannelFuturecf=sb.bind().sync();//服务器异步创建绑定 System.out.println(NettyServer.class+"启动正在监听:"+cf.channel().localAddress()); cf.channel().closeFuture().sync();//关闭服务器通道 }finally{ group.shutdownGracefully().sync();//释放线程池资源 bossGroup.shutdownGracefully().sync(); } } }

MyChannelHandlerPool

通道组池,管理所有websocket连接


/** *MyChannelHandlerPool *通道组池,管理所有websocket连接 *@authorzhengkai.blog.csdn.net *@date2019-06-12 */ publicclassMyChannelHandlerPool{ publicMyChannelHandlerPool(){} publicstaticChannelGroupchannelGroup=newDefaultChannelGroup(GlobalEventExecutor.INSTANCE); }

MyWebSocketHandler

处理ws一下几种情况:

channelActive与客户端建立连接

channelInactive与客户端断开连接

channelRead0客户端发送消息处理


/** *NettyServerNetty服务器配置 *@authorzhengkai.blog.csdn.net *@date2019-06-12 */ publicclassNettyServer{ privatefinalintport;  publicNettyServer(intport){ this.port=port; }  publicvoidstart()throwsException{ EventLoopGroupbossGroup=newNioEventLoopGroup();  EventLoopGroupgroup=newNioEventLoopGroup(); try{ ServerBootstrapsb=newServerBootstrap(); sb.option(ChannelOption.SO_BACKLOG,1024); sb.group(group,bossGroup)//绑定线程池 .channel(NioServerSocketChannel.class)//指定使用的channel .localAddress(this.port)//绑定监听端口 .childHandler(newChannelInitializer(){//绑定客户端连接时候触发操作  @Override protectedvoidinitChannel(SocketChannelch)throwsException{ System.out.println("收到新连接"); //websocket协议本身是基于http协议的,所以这边也要使用http解编码器 ch.pipeline().addLast(newHttpServerCodec()); //以块的方式来写的处理器 ch.pipeline().addLast(newChunkedWriteHandler()); ch.pipeline().addLast(newHttpObjectAggregator(8192)); ch.pipeline().addLast(newWebSocketServerProtocolHandler("/ws","WebSocket",true,65536*10)); ch.pipeline().addLast(newMyWebSocketHandler()); } }); ChannelFuturecf=sb.bind().sync();//服务器异步创建绑定 System.out.println(NettyServer.class+"启动正在监听:"+cf.channel().localAddress()); cf.channel().closeFuture().sync();//关闭服务器通道 }finally{ group.shutdownGracefully().sync();//释放线程池资源 bossGroup.shutdownGracefully().sync(); } } }

socket.html

主要是连接ws,发送消息,以及消息反馈


    Netty-Websocket  //byzhengkai.blog.csdn.net varsocket; if(!window.WebSocket){ window.WebSocket=window.MozWebSocket; } if(window.WebSocket){ socket=newWebSocket("ws://127.0.0.1:12345/ws"); socket.onmessage=function(event){ varta=document.getElementById('responseText'); ta.value+=event.data+" "; }; socket.onopen=function(event){ varta=document.getElementById('responseText'); ta.value="Netty-WebSocket服务器。。。。。。连接 "; }; socket.onclose=function(event){ varta=document.getElementById('responseText'); ta.value="Netty-WebSocket服务器。。。。。。关闭 "; }; }else{ alert("您的浏览器不支持WebSocket协议!"); } functionsend(message){ if(!window.WebSocket){return;} if(socket.readyState==WebSocket.OPEN){ socket.send(message); }else{ alert("WebSocket 连接没有建立成功!"); }  }          

服务端返回的应答消息

Controller

写好了html当然还需要一个controller来引导页面。


@RestController publicclassIndexController{  @GetMapping("/index") publicModelAndViewindex(){ ModelAndViewmav=newModelAndView("socket"); mav.addObject("uid",RandomUtil.randomNumbers(6)); returnmav; }  }

效果演示

6b5c9552-27df-11ed-ba43-dac502259ad0.png6b70c680-27df-11ed-ba43-dac502259ad0.png6b7ebaba-27df-11ed-ba43-dac502259ad0.png

改造netty支持url参数

1.首先,调整一下加载handler的顺序,优先MyWebSocketHandler在WebSocketServerProtocolHandler之上。


ch.pipeline().addLast(newMyWebSocketHandler()); ch.pipeline().addLast(newWebSocketServerProtocolHandler("/ws",null,true,65536*10)); 2.其次,改造MyWebSocketHandler的channelRead方法,首次连接会是一个FullHttpRequest类型,可以通过FullHttpRequest.uri()获取完整ws的URL地址,之后接受信息的话,会是一个TextWebSocketFrame类型。

publicclassMyWebSocketHandlerextendsSimpleChannelInboundHandler{ @Override publicvoidchannelActive(ChannelHandlerContextctx)throwsException{ System.out.println("与客户端建立连接,通道开启!"); //添加到channelGroup通道组 MyChannelHandlerPool.channelGroup.add(ctx.channel()); } @Override publicvoidchannelInactive(ChannelHandlerContextctx)throwsException{ System.out.println("与客户端断开连接,通道关闭!"); //添加到channelGroup通道组 MyChannelHandlerPool.channelGroup.remove(ctx.channel()); } @Override publicvoidchannelRead(ChannelHandlerContextctx,Objectmsg)throwsException{ //首次连接是FullHttpRequest,处理参数byzhengkai.blog.csdn.net if(null!=msg&&msginstanceofFullHttpRequest){ FullHttpRequestrequest=(FullHttpRequest)msg; Stringuri=request.uri(); MapparamMap=getUrlParams(uri); System.out.println("接收到的参数是:"+JSON.toJSONString(paramMap)); //如果url包含参数,需要处理 if(uri.contains("?")){ StringnewUri=uri.substring(0,uri.indexOf("?")); System.out.println(newUri); request.setUri(newUri); } }elseif(msginstanceofTextWebSocketFrame){ //正常的TEXT消息类型 TextWebSocketFrameframe=(TextWebSocketFrame)msg; System.out.println("客户端收到服务器数据:"+frame.text()); sendAllMessage(frame.text()); } super.channelRead(ctx,msg); } @Override protectedvoidchannelRead0(ChannelHandlerContextchannelHandlerContext,TextWebSocketFrametextWebSocketFrame)throwsException{ } privatevoidsendAllMessage(Stringmessage){ //收到信息后,群发给所有channel MyChannelHandlerPool.channelGroup.writeAndFlush(newTextWebSocketFrame(message)); } privatestaticMapgetUrlParams(Stringurl){ Mapmap=newHashMap<>(); url=url.replace("?",";"); if(!url.contains(";")){ returnmap; } if(url.split(";").length>0){ String[]arr=url.split(";")[1].split("&"); for(Strings:arr){ Stringkey=s.split("=")[0]; Stringvalue=s.split("=")[1]; map.put(key,value); } returnmap; }else{ returnmap; } } } 3.html中的ws地址也进行改造

socket=newWebSocket("ws://127.0.0.1:12345/ws?uid=666&gid=777"); 4.改造后控制台输出情况

收到新连接 与客户端建立连接,通道开启! 接收到的参数是:{"uid":"666","gid":"777"} /ws 客户端收到服务器数据:142531:这里输入消息 客户端收到服务器数据:142531:这里输入消息 客户端收到服务器数据:142531:这里输入消息

failed: WebSocket opening handshake timed out

听说是ssl wss的情况下才会出现,来自 @around-gao 的解决方法: 把MyWebSocketHandler和WebSocketServerProtocolHandler调下顺序就好了。

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    12

    文章

    8116

    浏览量

    82509
  • API
    API
    +关注

    关注

    2

    文章

    1382

    浏览量

    60990
  • 网络
    +关注

    关注

    14

    文章

    7251

    浏览量

    87440

原文标题:Spring Boot + Netty + WebSocket 实现消息推送

文章出处:【微信号:AndroidPush,微信公众号:Android编程精选】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    基于多路复用模型的Netty框架

    Netty version: 4.1.55.Final 传统的IO模型的web容器,比如老版本的Tomcat,为了增加系统的吞吐量,需要不断增加系统核心线程数量,或者通过水平扩展服务器数量,来增加
    的头像 发表于 09-30 11:30 556次阅读

    基于阿里云移动推送的移动应用推送模式最佳实践

    推送系统自动分配,通过接口获取2.2 账号与deviceID一一对应,对于同一设备切换账号的场景,通过重新绑定账号实现2.3 别名一个deviceID可以对应多个别名别名是用户粒度的概念,建议用于单推
    发表于 03-02 11:48

    如何实现服务器自动推送消息?

    有个想法,想和大家探讨一下如何实现。功能:自己在本地写个日志,第二天自动推送到手机上想法:想法不成熟,因为知识面太少了,目前想的是自己在本地电脑写个日志,上传给服务器,服务器第二天定时推送到指定邮箱上。想知道如何
    发表于 03-16 11:34

    怎么去理解netty

    导读原创文章,转载请注明出处。本文源码地址:netty-source-code-analysis两篇开胃小菜过后,我已经有一些粉丝了,还有一些粉丝加了我的好友,有粉丝通过微信对我的文章表示了肯定
    发表于 08-31 06:42

    怎样使用springboot整合netty来开发一套高性能的通信系统呢

    怎样使用springboot整合netty来开发一套高性能的通信系统呢?为什么要用这两个框架来实现通信服务呢?如何去实现呢?
    发表于 02-22 06:09

    网络编程框架netty io介绍

    深入理解网络编程框架netty io欢迎大家下载学习
    发表于 09-28 07:36

    如何采用mqtt协议实现物联网模块消息推送

    如何采用mqtt协议实现物联网模块消息推送
    发表于 11-03 06:55

    单片机MQTT如何实现推送的简单使用

    本文档的主要内容详细介绍的是单片机MQTT如何实现推送的简单使用。
    发表于 07-19 17:37 9次下载
    单片机MQTT如何<b class='flag-5'>实现</b><b class='flag-5'>推送</b>的简单使用

    如何使用SpringBoot集成Netty开发一个基于WebSocket的聊天室说明

    本文档的主要内容详细介绍的是基于SpringBoot,借助Netty控制长链接,使用WebSocket协议做一个实时的聊天室。
    发表于 05-29 17:56 1次下载
    如何使用SpringBoot集成<b class='flag-5'>Netty</b>开发一个基于WebSocket的聊天室说明

    Springboot整合netty框架实现终端、通讯板子(单片机)TCP/UDP通信案例

    如何springboot和netty案例的源代码一个springboot整合netty框架的开发小案例,实现服务端与单片机终端实时通信的通讯架构案例。物联网通信给板子下发指令案例附带源码及整合流程步骤
    发表于 12-29 18:55 19次下载
    Springboot整合<b class='flag-5'>netty</b>框架<b class='flag-5'>实现</b>终端、通讯板子(单片机)TCP/UDP通信案例

    详解Netty高性能异步事件驱动的网络框架

    大家好,今天我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架。
    的头像 发表于 03-16 10:57 1541次阅读

    netty推送消息接口及实现

    学过 Netty 的都知道,Netty 对 NIO 进行了很好的封装,简单的 API,庞大的开源社区。深受广大程序员喜爱。基于此本文分享一下基础的 netty 使用。实战制作一个 Netty
    的头像 发表于 11-02 16:14 1198次阅读

    一步步解决长连接Netty服务内存泄漏

    线上应用长连接 Netty 服务出现内存泄漏了!真让人头大
    的头像 发表于 04-27 14:06 522次阅读
    一步步解决长连接<b class='flag-5'>Netty</b>服务内存泄漏

    聊聊Netty那些事儿之从内核角度看IO模型

    从今天开始我们来聊聊Netty的那些事儿,我们都知道Netty是一个高性能异步事件驱动的网络框架。
    的头像 发表于 05-23 10:27 1094次阅读
    聊聊<b class='flag-5'>Netty</b>那些事儿之从内核角度看IO模型

    jdk17下netty导致堆内存疯涨原因排查

    天网风控灵玑系统是基于内存计算实现的高吞吐低延迟在线计算服务,提供滑动或滚动窗口内的 count、distinctCout、max、min、avg、sum、std 及区间分布类的在线统计计算服务
    的头像 发表于 09-12 11:22 411次阅读
    jdk17下<b class='flag-5'>netty</b>导致堆内存疯涨原因排查