DDPush 任意门推送

DDPush是什么

DDPush (Dimension Door Push),任意门推送,是一款开源免费的单机千万级实时信息推送服务器,使用Java语言开发,具有简单、稳定、高性能、高容量等特点,适用于互联网、移动互联网、物联网、Android、智能设备、硬件设备等各种环境。

DDPush可以做什么

移动互联网信息推送

DDPush可实时推送信息到各种Android、Windows等手机和平板(即“透传”),并支持双向通信。DDPush支持自定义信息,信息的格式和内容可由开发者自行定义

IM实时消息系统核心组件

通过集成DDPush,可以开发各种IM实时消息系统,例如:聊天系统、社交App等。

物联网设备控制与交互

DDPush可作为一个实时控制中心,控制物联网中的各种硬件设备(硬件需支持网络通信),与之双向通信。

DDPush有什么优势

开源、免费

DDPush采用Apache License Version 2.0开源协议,可放心使用,只要您保留其许可证信息。

容量高,速度快,要求低

DDPush在线部分主要采用UDP协议(同时支持TCP协议),支撑1000万终端在线的服务器,最少只需要4G内存(不考虑变长自定义信息的情况下),单个主流双核CPU使用率低于75%。即:一部普通PC台式机的配置。

DDPush推送部分采取TCP协议和Java NIO非阻塞网络技术,普通PC可支持至少数千台应用服务器同时长连接推送信息到终端,每秒推送信息的速度在1万条以上

终端设备流量少,省电

采用DDPush,智能手机等终端设备在线一个月(空载的情况下),只需几百KB的上载流量,下载流量甚至可调节到为零。

DDPush提供的Android手机App示例demo,连续在线48小时耗电少于0.5 mAh(使用2G网络GPRS连接,经360省电王测试  >>>详情)

DDPush基于什么技术

DDPush基于自有的二进制网络传输协议(基于TCP和UDP),因此客户端可以支持各种类型的终端设备,包括各种智能手机、平板、智能设备、物联网硬件,和各种终端操作系统(包括: Android, Windows, Linux等)。

DDPush使用Java语言开发,因此服务端可运行在各种操作系统和服务器上。

更多详细介绍请移步DDPush官网:http://www.ddpush.net/

一、准备工作

1、TCP/UDP协议,参见百度百科
2、Java NIO技术,参见Java NIO系列教程
3、下文提到的APPServer为我们自己的业务服务器,DDPush指推送服务器

二、工作流程

流程一、APPServer使用TCP模式向DDPush发送消息
流程二、DDPush再通过TCP或UDP(TCP vs UDP)方式透传给终端。

涉及到两个重要的类

1、NIOPushListener
第一步:启动APPServer TCP连接
public void initChannel() throws Exception{// 监听TCP连接channel = ServerSocketChannel.open();channel.socket().bind(new InetSocketAddress(port));channel.configureBlocking(false); // 非阻塞// 注册通道, 监听连接事件selector = Selector.open();channel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("NIO TCP Push Listener nio provider: "+selector.provider().getClass().getCanonicalName());
}

第二步:run方法,监听通道事件

@Override
public void run() {try{init();}catch(Exception e){e.printStackTrace();System.exit(1);}System.out.println("push listener port:"+this.port);while(!stoped && selector != null){try{handleEvent();handleTimeout(); // 处理超时的APPServer连接handleChannel(); // 处理通道事件}catch(java.nio.channels.ClosedSelectorException cse){//}catch (java.nio.channels.CancelledKeyException nx) {//}catch(Exception e){e.printStackTrace();}catch(Throwable t){t.printStackTrace();}}closeSelector();stopExecutor();}

第三步、分析handleChannel()方法

private void handleChannel() throws Exception{if(selector.select() == 0){try{Thread.sleep(1);}catch(Exception e){}return;}Iterator<SelectionKey> it = selector.selectedKeys().iterator();while (it.hasNext()) {SelectionKey key = it.next();it.remove();// Is a new connection coming in? APPServer新连接到达if (key.isAcceptable()) {try{ServerSocketChannel server = (ServerSocketChannel) key.channel();// APPServer连接对象SocketChannel channel = server.accept();channel.configureBlocking(false); // 非阻塞方式处理(对比ServerSocket得到Socket连接后, 需要开启线程去处理)channel.socket().setSoTimeout(sockTimout);//channel.socket().setReceiveBufferSize(1024);//channel.socket().setSendBufferSize(1024);PushTask task = new PushTask(this, channel);// 像Selector注册读通道channel.register(selector,SelectionKey.OP_READ, task);}catch(Exception e){e.printStackTrace();}}if (key.isReadable() || key.isWritable()) {try{PushTask task = (PushTask)key.attachment();if(task == null){//this should never happencancelKey(key);continue;}task.setKey(key);// 向终端推送消息executor.execute(task);}catch(Exception e){e.printStackTrace();}}}}

第2行:selector.select()方法会一直阻塞(wakeup方法会取消阻塞,立即返回)直到通道上有订阅的事件
第16行:表示有APPServer连接到DDPush了

第20行:channel可以理解为一个APPServer连接对象
第27行:向channel注册读事件,可以理解等待APPServer发消息,同时将task这个对象附件进去(后面会讲解PushTask作用)
第33行:表示准备APPServer发来消息,或消息已经接收完毕准备回应APPServer
第42行:可以理解为向终端推送消息,当然这里面包含读取APPServer发来的消息、响应APPServer等流程
2、PushTask
负责处理每一个连接到DDPush的APPServer,可以理解为一个APPServer对应一个PushTask
第一步、run()方法
@Overridepublic synchronized void run() {if(listener == null || channel == null){return;}if(key == null){return;}if(isCancel == true){return;}try{if(writePending == false){if(key.isReadable()){ // 可读状态//read pkg 读取APPServer推送的信息readReq();}else{// do nothing}}else{//has package// try send pkg and place hasPkg=false////register write ops if not enough buffer//if(key.isWritable()){writeRes(); // 将响应信息发给APPServer//}}}catch(Exception e){cancelKey(key);isCancel = true;}catch(Throwable t){cancelKey(key);isCancel = true;}key = null;}

第14行:判断消息是否接受完毕
第18行:读取APPServer消息

第28行:响应APPServer
下面重点分析readReq()和writeRes()方法
第二步、readReq()方法
/*** 读取APPServer推送的信息* @throws Exception*/private void readReq() throws Exception{if(this.writePending == true){return;}if(channel.read(buffer) < 0){throw new Exception("end of stream");}if(this.calcWritePending() == false){ // 判断消息是否接收完毕return;}else{byte res = 0;try{// 读取具体信息, 推送给终端processReq();}catch(Exception e){res = 1;}catch(Throwable t){res = -1;}// 响应信息信息(0表示成功)buffer.clear();buffer.limit(1);buffer.put(res);buffer.flip();// 注册写事件registerForWrite(key, true);}lastActive = System.currentTimeMillis();}

第10行:channel.read(buffer)这个方法负责从APPServer读取消息,类似我们从文件读取流一样,每次读取一定的数量,所以我们需要判断何时消息读取完毕

第13行:判断消息是否读取完毕,如果没有读取完毕则return,那么return到哪里呢?回到我们刚刚NIOPushListener的handleChannel()方法,如果消息未完毕,又会触发PushTask的run()方法,继续接受消息,一旦消息接受完毕,代码会走到第19行
第19行:processReq()方法的作用是将APPServer发过来的消息透传给终端(流程二),此方法代码虽然不多,但涉及到东西很多,下篇文章分析到终端连接DDPush的地方会详细讲解
第三步、writeReq()方法
/*** 响应APPServer* @throws Exception*/private void writeRes() throws Exception{if(buffer.hasRemaining()){channel.write(buffer);}else{buffer.clear();buffer.limit(Constant.PUSH_MSG_HEADER_LEN);this.writePending = false;registerForWrite(key, false);}lastActive = System.currentTimeMillis();}

第6行:表示是否已经全部将响应消息发送给APPServer了

第7行:发送响应消息,这个和判断消息是否读取完毕类似,可能会触发多次,所以需要第6行的判断,也就是说PushTask的run()方法可能会被执行多次
好了,上面是关于APPServer向DDPush推送消息的源码分析,下篇文章会给大家带来DDPush与终端连接的源码分析,敬请期待!

DDPush开源推送框架源码分析之APPServer到DDPush相关推荐

  1. 基于Java毕业设计新闻推送系统源码+系统+mysql+lw文档+部署软件

    基于Java毕业设计新闻推送系统源码+系统+mysql+lw文档+部署软件 基于Java毕业设计新闻推送系统源码+系统+mysql+lw文档+部署软件 本源码技术栈: 项目架构:B/S架构 开发语言: ...

  2. Spark RPC框架源码分析(二)RPC运行时序

    前情提要: Spark RPC框架源码分析(一)简述 一. Spark RPC概述 上一篇我们已经说明了Spark RPC框架的一个简单例子,Spark RPC相关的两个编程模型,Actor模型和Re ...

  3. Linux驱动修炼之道-SPI驱动框架源码分析(上)

    Linux驱动修炼之道-SPI驱动框架源码分析(上)   SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设 ...

  4. Android框架源码分析——从设计模式角度看 Retrofit 核心源码

    Android框架源码分析--从设计模式角度看 Retrofit 核心源码 Retrofit中用到了许多常见的设计模式:代理模式.外观模式.构建者模式等.我们将从这三种设计模式入手,分析 Retrof ...

  5. SPI驱动框架源码分析

     SPI驱动框架源码分析 2013-04-12 16:13:08 分类: LINUX SPI驱动框架源码分析 SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设 ...

  6. php+yii框架,yii框架源码分析(一)

    yii框架源码分析(一) 本文将对yii中的mvc,路由器,filter,组件机制等最主要的部分进行自己的一点浅析,力求说明自己做一个php mvc不是那么的遥不可及,其实是很简单的. 源码基于yii ...

  7. S3C24XX DMA框架源码分析

    基于S3C2440 的DMA 框架源码分析 基于S3C2440 的DMA 框架源码分析 二寻根溯源 1 设备类的注册 2 s3c2410_dma_init 3 s3c24xx_dma_order_se ...

  8. golang gin框架源码分析(二)---- 渐入佳境 摸索Engine ServeHTTP访问前缀树真正原理

    文章目录 全系列总结博客链接 前引 golang gin框架源码分析(二)---- 渐入佳境 摸索Engine ServeHTTP访问前缀树真正远原理 1.再列示例代码 从示例代码入手 2.r.Run ...

  9. Java集合类框架源码分析 之 LinkedList源码解析 【4】

    上一篇介绍了ArrayList的源码分析[点击看文章],既然ArrayList都已经做了介绍,那么作为他同胞兄弟的LinkedList,当然必须也配拥有姓名! Talk is cheap,show m ...

最新文章

  1. GNOME 的新夜灯功能旨在帮助你睡得更好
  2. openoffice linux 目录,Linux之安装OpenOffice
  3. java 判断二叉树是否平衡_剑指Offer - 判断二叉树是否是平衡二叉树
  4. 【转】6 Reasons Why JavaScript’s Async/Await Blows Promises Away (Tutorial)
  5. C# 网络编程之webBrowser乱码问题及解决知识
  6. 音视频技术开发周刊 | 162
  7. phpstorm破解安装
  8. Django(part8)--响应及HttpResponse对象
  9. c++中,可以用类名直接访问非静态成员函数?
  10. Android插件化开发之运行未安装apk的activity
  11. 转码器ffmpeg安装
  12. 计算机三级之嵌入式系统学习笔记1
  13. GridView样式用代码来设置
  14. wifi频谱仪测试软件,无线局域网频谱分析仪 (Spectrum XT)
  15. OpenGL ES 之 2D 纹理介绍和使用
  16. T00ls Lpk Sethc 全新v2.0版(附LPK提权)
  17. 实现函数指针的功能,tr1::bind,tr1::function,virtual函数重载
  18. windows常见开机报错码以及解决方法
  19. vrchat模型保存_VRchat下载别人的模型
  20. kdj超卖_如何正确理解KDJ?

热门文章

  1. 计算给定数据集的香农熵
  2. mqtt协议调用示例(包括MQTT一键启动服务+测试工具 MQTTFX云盘下载),对捷顺门禁温感一体机进行人员信息下发
  3. php 文件选择框,利用php+mcDropdown实现文件路径可在下拉框选择
  4. Python爬虫笔记之用BeautifulSoup及requests库爬取
  5. 室内设计——欧式风格室内设计(包含预览图jpg和.psd文件).zip
  6. smart700iev3 程序下载设置_smart line 700ie v3触摸屏下载不了程序-工业支持中心-西门子中国...
  7. spring boot 事务_一个基于 RabbitMQ 的可复用的分布式事务消息架构方案!
  8. songtaste资源下载程序
  9. 广州系统集成项目管理工程师报考
  10. android 如何构建半屏显示的界面_如何实现android设备进入recovery界面后自动重启...