应用场景:设备为安卓、PC以及服务器,要求PC端能够单向给移动端发送消息指令,安卓端解析消息,进行后续处理动作。其中安卓端为基于Phonegap开发,说白了,就是HTML+JS。

规模:正常应用为200移动端,PC端数量有限,不超过10台,最多移动端为不超过500台。

可以看出这是一个很小规模的应用,也正如此,才可以给我像这样大方的保有HTTP连接不释放的机会。

当前背景:目前关于推送的实现,无非就是谷歌,HTML5的websocket,韩国某牛写的androidpn,以及第三方和伪推送方式。

谷歌的推送在中国大陆据说不稳定,所以被中国人弃之不用,然后就是HTML5的websocket居然在安卓4.0的机器上还不能被很好的支持,这些足以让那位韩国人写的androidpn在国内火了一阵子,不过后来因为国内的第三方推送开始发力,大部分应用开发者只要不是特别需要的话,就不会自己再做推送了。而伪推送方式,无外乎就是HTTP的长连接或者AJAX的长轮询,以及iframe流的方式(或许还有其他方式),这种技术就被称为comet。

基本原理:安卓端页面不间断的发起轮询请求,服务器接收请求后,如果没有消息可以返回,就先不释放连接,即线程等待,等待超时或者中途被唤醒后,返回给页面,释放连接,安卓端的页面再次发起轮询请求。

服务器端接收到PC端指令后,唤醒等待线程,让安卓端的下次轮询可以获取消息。

代码实现:

服务器端启动时,像ServletContext内添加一个map用于存储PC端像安卓端发送的消息。

public class AppListener implements ServletContextListener{//监听ServletContext的初始化@Overridepublic void contextDestroyed(ServletContextEvent arg0) {// TODO Auto-generated method stub

}

@Overridepublic void contextInitialized(ServletContextEvent event) {// TODO Auto-generated method stubevent.getServletContext().setAttribute(Constant.IMMSG, new HashMap());

System.out.println("添加Map成功");

}

}

View Code

接收安卓端长轮询的servlet:

private static int num=0;public void service(HttpServletRequest req,HttpServletResponse res) throws UnsupportedEncodingException{

req.setCharacterEncoding("UTF-8");

res.setContentType("text/html,charset=UTF-8");

ServletContext application=req.getSession().getServletContext();

req.getParameter("userID");

HashMapmsg=new HashMap();

Map map=((Map)application.getAttribute(Constant.IMMSG));synchronized(map){

String temp=map.remove(req.getParameter("userID"));

if(temp==null||temp.trim().equals("")){

try {

System.out.println("休眠等待60秒"+(++num));

map.wait(60000);//服务器保留此连接60秒

msg.put("msg","nomsg");//没有消息时,返回nomsg

} catch (InterruptedException e) {

blockmsg.put("msg", "error");

e.printStackTrace();

}

}else{

msg.put("msg", temp);//如果有消息,则立刻返回

}

}

PrintWriter out;try {

out = res.getWriter();

out.print(JSONObject.fromObject(msg));

out.flush();

out.close();

System.out.println("----等待数"+(--num));

} catch (IOException e) {

e.printStackTrace();

}

}

View Code

接收PC端消息的Servlet:

public class SendMsgService extends HttpServlet {public void service(HttpServletRequest req,HttpServletResponse res) throws UnsupportedEncodingException{

req.setCharacterEncoding("UTF-8");

res.setContentType("text/html,charset=UTF-8");

ServletContext application=req.getSession().getServletContext();

Map map=((Map)application.getAttribute(Constant.IMMSG));synchronized(map){

map.put(req.getParameter("userID"), req.getParameter("msg"));

map.notifyAll();//通知所有等待的线程,让安卓端发起下次轮询    }

}

View Code

所谓安卓端的页面就是简单的js,在一次请求结束后发起下一次请求而已。

function longPolling(){

$.ajax({             //url:ip+'/haveMsg',

url:"http://192.168.1.109:8081/mobileinspect/haveMsg",

data:{'userID':111},

dataType:'json',

timeout:70000,

cache:false,

type:"post",

success:function(data){                 if(data.msg){                     if(data.msg=="nomsg"){

window.setTimeout(longPolling,1000)

}else{

navigator.notification.confirm(data.msg,onConfirm,"新的消息","接受,拒绝");

window.setTimeout(navigator.notification.beep(1),100);

window.setTimeout(longPolling,1000)

}

}

},

error:function(xhr,err){//如果出现错误,则在十秒钟之后,再进行长轮询

window.setTimeout(longPolling,10000)

}

})

}

View Code

然后就是修改Tomcat的最大连接数,以让服务器能够处理这么多的连接而不至于停止响应:

针对我的这个应用,最大600个处理线程足以应付那500台机器了。单纯我的办公电脑就可以支持发起500个HTTP连接,并由本地的Tomcat处理,相信服务器更能够轻松应付。

另外,需要注意的是:据说单机windows下只支持2000左右的HTTP连接,而Linux下约是1000个,所以各位如果使用这种方法的时候,要注意是否会超出这些限制。

为什么要服务器hold住连接一段时间后释放呢?主要是因为长时间的静态连接容易出问题,另外移动端的网络复杂,所以才会有释放的必要。

mysql 长轮询_基于HTTP长轮询实现简单推送相关推荐

  1. java 长轮询_基于springboot 长轮询的实现操作

    springboot 长轮询实现 基于 @EnableAsync , @Sync @SpringBootApplication @EnableAsync public class DemoApplic ...

  2. java线程轮询_基于springboot实现轮询线程自动执行任务

    本文使用: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务.使用这种方式可以让你的程序按照某一个频度执行, 但不能在指定 ...

  3. 最简单的基于FFmpeg的推流器(以推送RTMP为例)

    ===================================================== 最简单的基于FFmpeg的推流器系列文章列表: <最简单的基于FFmpeg的推流器(以 ...

  4. php 长连接心跳_支持gRPC长链接,深度解读Nacos2.0架构设计及新模型

    作者 | 杨翊(席翁) Nacos PMC 来源|阿里巴巴云原生公众号 Nacos 简介 Nacos 在阿里巴巴起源于 2008 年五彩石项目,该项目完成了微服务拆分和业务中台建设,随着云计算和开源环 ...

  5. php消息实时推送技术,基于HTTP协议之WEB消息实时推送技术原理及实现

    很早就想写一些关于网页消息实时推送技术方面的文章,但是由于最近实在忙,没有时间去写文章.本文主要讲解基于 HTTP1.1 协议的 WEB 推送的技术原理及实现.本人曾经在工作的时候也有做过一些用到网页 ...

  6. 基于腾讯信鸽设计一个微型推送服务

    今日科技快讯 据印度媒体报道,对于旗下短视频应用抖音国际版TikTok在印度遭封杀,母公司字节跳动表现得似乎"非常乐观",并计划未来三年在印度投资10亿美元.在接受采访时,字节跳动 ...

  7. 基于 WebSocket 的实时通告功能,推送在线与未登录用户

    在我们以往的软件或者网站使用中,都有遇到过这种情况,莫名的弹出广告或者通知!而在我们的业务系统中,有的时候也需要群发通知公告的方式去告知网站用户一些信息,那么这种功能是怎么实现的呢,本 Chat 将使 ...

  8. 基于SolrCloud的内容搜索和热点推送

    原文出自[听云技术博客]:http://blog.tingyun.com/web/article/detail/556 什么是热点 我认为热点有时效性和受众面 用户关注从低到高再到低的内容 .有公共热 ...

  9. 基于openfire+smack的Android、消息推送服务

    前言 Java领域的即时通信的解决方案可以考虑openfire+spark+smack.当然也有其他的选择. Openfire 是基于Jabber协议(XMPP)实现的即时通信服务器端版本,目前建议使 ...

最新文章

  1. iOS应用模块化的思考及落地方案(二)模块化自动构建工具的使用
  2. python-dotenv的使用
  3. linux系统虚拟化测试,网络性能与磁盘测试 - Linux虚拟化性能PK:Ubuntu系统6大版本_Linux新闻_Linux公社-Linux系统门户网站...
  4. 试题 G: 外卖店优先级 第十届蓝桥杯
  5. 听技术播客:一边学Python编程一边学英语
  6. curd什么意思中文_每日一句英译英:She's a ten什么意思?
  7. Java工作笔记-生成及解析Json字符串
  8. Elasticsearch--linux网络设置 开启密码访问---全文检索引擎ElasticSearch工作笔记021
  9. 与中石油分享SOA成功实践
  10. 小程序WXML 使用小结
  11. AR/VR learning (2)--unity3D在android 上的手势识别与检测
  12. Minecraft 1.12.2模组开发(三十七) 3D盔甲
  13. 别错过 孩子学19种才艺的最佳年龄
  14. 财务机器人正式上岗,一个机器顶40个人!
  15. gwt php,java – 启动GWT项目的PHP程序员的任何好技巧?
  16. [湖南大学程序设计实训训练作业一]7.F1方程式冠军(灵活运用下标来简化代码)
  17. java中String xx xx_Java中常用String方法
  18. 修改Docker默认安装路径
  19. Nginx高级优化(2): shell脚本日志切割,连接超时,进程数,网页压缩,防盗链,FPM 参数优化!!
  20. 使用sws_scale转换视频、使用swr_convert转换音频

热门文章

  1. mysql安装最后两项无响应,win10下安装mysql8.0.23 及 “服务没有响应控制功能”问题解决办法...
  2. 怎么把python和pycharm关联_Python3 安装pylint 及与PyCharm关联
  3. 第八篇:稳定性之提升团队潜意识【及时复盘、开关设计】
  4. java中常用的IO,你可否分得清、流的分类
  5. Python机器学习:评价分类结果003实现混淆矩阵,精准率和召回率
  6. GP学习(七)—Accessing raster workspaces
  7. html 再按一次退出,【劲爆、独家】拦截再按一次退出应用,改成单击back隐藏到后台...
  8. make,make install命令
  9. 用几何语言表示线段ab的中点c,做完这30道精选题,你的几何图形绝对满分!
  10. 两位小数乘两位小数竖式_冀教版五年级数学上册2.4小数乘小数微课视频 | 练习...