精华内容
下载资源
问答
  • ddpush ddpush 的Docker container 测试服务器:121.40.250.221,端口都是默认。10M带宽,欢迎大家来测试! 如果测试人数比较多,我会公布测试结果!服务器暂时2016年3月1日到期! 谢谢! usage: docker pull nb7123...
  • 个人为了学习将DDPush放到github中,官网地址 ,以下摘自官网。 DDPush 概述 IM(Instant Messaging)即时通讯系统,从1996年ICQ的出现,到国际巨头割据的今天,已经深刻地影响了互联网,甚至人类社会的变化。从移动...
  • DDpush部分带注释

    2018-05-12 14:21:57
    DDpush,代码包含服务器端与android端,部分类中带注释,易懂
  • DDPush DDPush任意门推送,开源免费实时信息推送服务器,官网地址 此项目非官方上传,学习之用,加入了部分代码的分析。 DDPush:服务端实现源码 DDPushClientDemoTCP:TCP模式Android客户端DEMO ...
  • ddpush-1.0.0.3下载

    2018-10-10 15:34:00
    ddpush-1.0.0.3下载
  • DDPush服务器端源代码

    2016-02-21 12:25:47
    DDPush服务器端源代码
  • DDPush任意门推送

    2014-12-03 12:51:55
    DDPush任意门推送, 千万在线即时通知推送 DDPush任意门推送
  • android ddpush

    2014-11-03 08:54:04
    http://www.ddpush.net/download-v10
    http://www.ddpush.net/download-v10
    
    展开全文
  • DDpush 推送功能代码

    2015-12-29 15:30:32
    DDpush实现推送功能, 测试成功并引入项目完整实现推送功能!
  • 推送DDpush

    2018-05-08 09:01:30
    ddpush提供了两种连接方式。UDP 和 TCP 官方说明。 UDP比TCP的同时连接数要多很多倍。所以推荐用UDP的方式。 ddpush是用来做推送的。所以说一下。首先ddpush服务器端建立UDP或者TCP服务器。 然后监听服务器的9966...

    工作流程:

    首先。ddpush提供了两种连接方式。UDP 和 TCP 官方说明。 UDP比TCP的同时连接数要多很多倍。所以推荐用UDP的方式。 ddpush是用来做推送的。所以说一下。首先ddpush服务器端建立UDP或者TCP服务器。 然后监听服务器的9966端口 UDP 和TCP都是使用这个端口。在这里也顺便说一下。电脑的端口。UDP有的端口、TCP也可有。所以UDP使用9966端口。TCP也可以使用9966端口。TCP的是监听、UDP的是绑定。 没怎么具体看资料。我这说的就是让大家明白。UDP 使用9966端口的同时TCP也可以使用9966端口。 
    ddpush服务器监听9966端口之后。客户端用对应的TCP或者UDP连接服务器的这个端口。服务器在收到一个客户端连接的时候。会创建一个客户端的虚拟对象。保存到一个集合里。这个对象里保存了这个对象的uuid(常规来说是md5加密的字符串) 还有这个客户端的网络地址、最后心跳时间、是否有消息需要推送给这个客户端等等一些属性。 
    具体可以查看org.ddpush.im.v1.node下的ClientStatMachine.java 这个类。 客户端链接之后。服务器根据这个客户端生成一个ClientStatMachine对象。保存在集合中。 这个集合就是所有连接过服务器的客户端对象集合。这个集合在正常关闭服务器的时候。会被保存到文件中。当ddpush服务器下次启动的时候。就会从文件中读取上次关闭服务器时。保存的客户端对象。

    这样 客户端就和服务器端建立了连接、当然这个连接应为各种路由端口映射等问题。需要不时的发送或者接受数据、来告诉路由器这个连接正在使用。避免这个连接被释放。所以ddpush里有心跳机制。 也就是定时 从客户端向服务器端发送消息。如果在一段时间内。服务器没有收到客户端的心跳消息。那么服务器就会认为这个客户端掉线了。 ddpush默认的心跳时间应该是50秒。 大家可以按照自己的需要去修改。

    然后我们开始说推送。 ddpush主要是用来从服务器向客户端推送消息。没有从客户端向服务器推送消息。也同时没有客户端向客户端推送消息。 如果有这方面的需要可以自行找解决办法。 当然我这样说。可能有人说 ddpush的客户端也向服务器发送消息。对!是这样的。ddpush的客户端也向服务器发送消息。 
    但是: ddpush的客户端向服务器发送的所有消息只有两种类型: 
    第一种是心跳消息 
    第二种是应答消息

    首先第一种消息 心跳消息 这个就不说了。就是为了保持长连接的状态 定时从客户端向服务器发送的消息 
    第二种:应答消息 ddpush为了保证客户端接收服务器端推送的消息的到达率 而设计的。 正常情况下 ddpush服务器像客户端推送一个消息。 客户端收到了这条消息 同时将这条消息转发给服务器。服务器接收到了这条转发过来的消息 就知道 这个客户端已经成功的接收到了这条下发的推送消息 然后就把服务器保存的虚拟客户端对象中的 是否有这类消息 设置成 false 如果服务器下发消息之后。没有收到这个客户端反馈的消息。服务器就会在下次接收到客户端心跳的时候 向这个客户端再次发送这条推送消息、直到客户端向服务器发送了响应消息。

    好了以上就是ddpush的服务器像客户端推送一条消息的一半的过程。为什么说是一半的。应为我们还没有说 是谁让ddpush服务器向哪个客户端推送消息。下面来介绍一下 怎么告诉ddpush服务器 让ddpush服务器向某个(例如:100001) 用户推送消息

    向ddpush服务器发送推送任务的是org.ddpush.im.v1.client.appserver里面的 Pusher.java 这个类。 
    里面提供了几种方式 推送0x10消息 推送0x11消息 推送0x20消息 也就是说我们需要用Pusher.java 来告诉ddpush服务器 我要给100001这个用户推送一条 0x10 这种消息 然后ddpush服务器接受到了这个任务。就从 客户端虚拟客户端对象集合中查找这个用户。如果这个用户没有查找到。就根据这条推送消息来创建一个虚拟的用户对象 并存放到虚拟客户端对象集合中 当这个用户登录ddpush服务器之后 ddpush发现服务器已经存在了这个用户。就从虚拟客户端对象集合中把这个用户取出。然后修改这个客户端对象的属性。 同时发现在虚拟客户端对象中有一条需要推送的消息。于是就立即把这条消息推送给这个刚上线的客户端。

    这就是怎么告诉ddpush服务器要给谁推送什么样的任务。  
    这个向ddpush服务器发布推送任务的过程是 ddpush在启动的时候 同时启动了一个接受推送任务的服务器 这个服务器监听9999端口。 然后 在有要推送的任务的时候。我们创建Pusher.java 这个类的对象。在这个类中。就是连接到ddpush服务器的9999端口。然后 向ddpush发送相对应的数据包。然后ddpush接受到了这个推送任务数据包。检查数据包格式、判断推送任务类型。取出这个推送目标的uuid 从 虚拟客户端对象集合中查找这个uuid 找不到就根据这个推送消息包创建一个 虚拟客户端对象 并将这条推送消息存入这个 虚拟客户端对象中 再把这个对象存到 虚拟客户端对象集合当中。 然后就是上面的过程。 当这个客户端上线的时候。ddpush就发现了有这个客户端对象同时也有一条他的数据。所以这个客户端在上线的时候就会立即收到这条推送消息。

    好了基本上ddpush就是这个流程。 同时说一下。ddpush 只能推送最后一条消息给客户端。也就是说ddpush没有推送消息列表 当一条消息被发送到ddpush中 ddpush服务器发送给客户端 如果客户端此时不在线。则肯定是收不到这条推送消息。然后当有第二条消息需要推送给这个用户的时候。 ddpush会抛弃第一个客户端并没有接收到的推送消息。然后开始推送第二条消息。 如果第二条消息客户端也没有收到。并且这时候有第三条或者更多的推送消息需要推送给这个客户端。则ddpush只会保留最后一条推送消息 在这个客户端下次上线的时候 推送给这个客户端。



    展开全文
  • 国内DDPush消息推送

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

    千次阅读 2017-10-25 10:41:43
    ddpush推送介入项目解释

    之前写了一个android小项目用到了ddpush推送,自己感觉很好用也很简单,没有友盟,极光等有附加的东西,相对jar包也小了很多.因为之前公司需要,也就是前端缺人我就零时去补了一下,好久没有写过前端了,好多框架都不会用了,反正忙的是焦头烂额,忙了差不多两个月最近稍微轻松了一点.  昨天是1024说是程序员节.但是

    我连个码畜都不是啊,以后在也不和别人说是程序员了  ,就说搞电脑的好了.

     

     

     

     

     

    上面的都是题外话.接下来介绍下ddpush和其使用方法.

    http://www.ddpush.net/  

    上面的是ddpush的网址,我自己觉得ddpush的最大有点的jar包小,还有就是耗电量小.别的开发中没有明显感觉.

     

    ddpush的官网  其实上面的东西想看就看下不看也没事.直接  找到下载

    红色的区域下载下来

    DDPush Server 是服务端需要配置的

    Android的话只要下载安坐端App示例就行了,Android主要分为UDP和TCP,这个你要根据你项目的需求来选择. 

    TCP和DUP的最本质区别就是一个安全一个不安全,就是多一个校验,速度有点区别

    TCP需要检验,也就是通俗的三次握手

    UDP不不要

    选着的时候要根据自己的具体要求选着 ,我之前的这个项目就是因为后端只支持TCP所以就用ddpush TCP

    导入jar包 ,jar包在下载的Android案例代码里有

    在libs里

    然后把案例中的代码直接复制过来

    package pad.android.grabsingle.ddpush.service;
    
    import android.app.AlarmManager;
    import android.app.Notification;
    import android.app.NotificationManager;
    import android.app.PendingIntent;
    import android.app.Service;
    import android.content.Context;
    import android.content.Intent;
    import android.content.SharedPreferences;
    import android.os.IBinder;
    import android.os.PowerManager;
    import android.os.PowerManager.WakeLock;
    
    import org.ddpush.im.v1.client.appuser.Message;
    import org.ddpush.im.v1.client.appuser.TCPClientBase;
    
    import pad.android.grabsingle.activity.ConstructionMain;
    import pad.android.grabsingle.been.DDpushNotice;
    import pad.android.grabsingle.api.SysConfig;
    import pad.android.grabsingle.ddpush.Params;
    import pad.android.grabsingle.ddpush.Util;
    import pad.android.grabsingle.ddpush.receiver.TickAlarmReceiver;
    import pad.android.grabsingle.utils.tools.AppUtil;
    import pad.android.grabsingle.utils.tools.RxBus;
    
    public class OnlineService extends Service {
    	
    	protected PendingIntent tickPendIntent;
    	protected TickAlarmReceiver tickAlarmReceiver = new TickAlarmReceiver();
    	WakeLock wakeLock;
    	MyTcpClient myTcpClient;
    	Notification n;
    	private ConstructionMain constructionMain;
    
    	public static void reset(Context context) {
    		Intent intent = new Intent(context, OnlineService.class);
    		intent.putExtra("CMD", "RESET");
    		context.startService(intent);
    	}
    
    	public class MyTcpClient extends TCPClientBase {
    
    
    		public MyTcpClient(byte[] uuid, int appid, String serverAddr, int serverPort)
    				throws Exception {
    			super(uuid, appid, serverAddr, serverPort, 10);
    
    		}
    
    		@Override
    		public boolean hasNetworkConnection() {
    			return Util.hasNetwork(OnlineService.this);
    		}
    		
    
    		@Override
    		public void trySystemSleep() {
    			tryReleaseWakeLock();
    		}
    
    		@Override
    		public void onPushMessage(Message message) {
    			if(message == null){
    				return;
    			}
    			if(message.getData() == null || message.getData().length == 0){
    				return;
    			}
    			if(message.getCmd() == 16){}// 0x10 通用推送信息
    			if(message.getCmd() == 17){}// 0x11 分组推送信息
    			if(message.getCmd() == 32){// 0x20 自定义推送信息
    				DDpushNotice dDpushNotice=new DDpushNotice();
    				dDpushNotice.notice=""+(Math.random()*100);
    				RxBus.getDefault().post(dDpushNotice);
    			}
    			setPkgsInfo();
    		}
    
    	}
    
    	public OnlineService() {
    	}
    
    	@Override
    	public void onCreate() {
    		super.onCreate();
    		this.setTickAlarm();
    		PowerManager pm = (PowerManager) this.getSystemService(Context.POWER_SERVICE);
    		wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "OnlineService");
    		resetClient();
    	}
    
    	@Override
    	public int onStartCommand(Intent param, int flags, int startId) {
    		if(param == null){
    			return START_STICKY;
    		}
    		String cmd = param.getStringExtra("CMD");
    		if(cmd == null){
    			cmd = "";
    		}
    		if(cmd.equals("TICK")){
    			if(wakeLock != null && wakeLock.isHeld() == false){
    				wakeLock.acquire();
    			}
    		}
    		if(cmd.equals("RESET")){
    			if(wakeLock != null && wakeLock.isHeld() == false){
    				wakeLock.acquire();
    			}
    			resetClient();
    		}
    		if(cmd.equals("TOAST")){
    			String text = param.getStringExtra("TEXT");
    			if(text != null && text.trim().length() != 0){
    //				Toast.makeText(this, text, Toast.LENGTH_LONG).show();
    			}
    		}
    		
    		setPkgsInfo();
    
    		return START_STICKY;
    	}
    	
    	protected void setPkgsInfo(){
    		if(this.myTcpClient == null){
    			return;
    		}
    		long sent = myTcpClient.getSentPackets();
    		long received = myTcpClient.getReceivedPackets();
    		SharedPreferences account = this.getSharedPreferences(Params.DEFAULT_PRE_NAME, Context.MODE_PRIVATE);
    		SharedPreferences.Editor editor = account.edit();
    		editor.putString(Params.SENT_PKGS, ""+sent);
    		editor.putString(Params.RECEIVE_PKGS, ""+received);
    		editor.commit();
    	}
    	
    	protected void resetClient(){
    		SharedPreferences account = this.getSharedPreferences(Params.DEFAULT_PRE_NAME, Context.MODE_PRIVATE);
    		String serverIp = SysConfig.webService_old_ip;
    		String serverPort = "9966";
    		String pushPort = "9999";
    		String userName = AppUtil.getSharedPreferenceValue(this, "username", "");
    		if(serverIp == null || serverIp.trim().length() == 0
    				|| serverPort == null || serverPort.trim().length() == 0
    				|| pushPort == null || pushPort.trim().length() == 0
    				|| userName == null || userName.trim().length() == 0){
    			return;
    		}
    		if(this.myTcpClient != null){
    			try{myTcpClient.stop();}catch(Exception e){}
    		}
    		try{
    			myTcpClient = new MyTcpClient(Util.md5Byte(userName), 1, serverIp, Integer.parseInt(serverPort));
    			myTcpClient.setHeartbeatInterval(50);
    			myTcpClient.start();
    			SharedPreferences.Editor editor = account.edit();
    			editor.putString(Params.SENT_PKGS, "0");
    			editor.putString(Params.RECEIVE_PKGS, "0");
    			editor.commit();
    		}catch(Exception e){
    //			Toast.makeText(this.getApplicationContext(), "操作失败:"+e.getMessage(), Toast.LENGTH_LONG).show();
    		}
    //		Toast.makeText(this.getApplicationContext(), "ddpush:终端重置", Toast.LENGTH_LONG).show();
    	}
    	
    	protected void tryReleaseWakeLock(){
    		if(wakeLock != null && wakeLock.isHeld() == true){
    			wakeLock.release();
    		}
    	}
    	
    	protected void setTickAlarm(){
    		AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    		Intent intent = new Intent(this,TickAlarmReceiver.class);
    		int requestCode = 0;  
    		tickPendIntent = PendingIntent.getBroadcast(this,
    		requestCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    		//小米2s的MIUI操作系统,目前最短广播间隔为5分钟,少于5分钟的alarm会等到5分钟再触发!2014-04-28
    		long triggerAtTime = System.currentTimeMillis();
    		int interval = 300 * 1000;  
    		alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime, interval, tickPendIntent);
    	}
    	
    	protected void cancelTickAlarm(){
    		AlarmManager alarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    		alarmMgr.cancel(tickPendIntent);  
    	}
    	
    	protected void cancelNotifyRunning(){
    		NotificationManager notificationManager=(NotificationManager)this.getSystemService(Context.NOTIFICATION_SERVICE);
    		notificationManager.cancel(0);
    	}
    
    	@Override
    	public void onDestroy() {
    		super.onDestroy();
    		//this.cancelTickAlarm();
    		cancelNotifyRunning();
    		this.tryReleaseWakeLock();
    	}
    	
    	@Override
    	public IBinder onBind(Intent intent) {
    		return null;
    	}
    }
    

     

     

     

     

    这个地方是设置接收service.ddpush推送的配置点

    serverIp   配置服务器IP

    serverPort 服务器端口号 默认是9966 (不用改)

    pushPort 客户端端口号        默认9999(不用改)

    onPushMessage 这个方法是接收ddpush推送的消息的

    当返回码为16的时候  接收通用消息

    当返回码为17的时候,接收分组消息

    当返回码为32的时候是自定义消息

    如果推送的消息只是短信提示的之类的话

    但我这边是有特殊需求所以服务器用的是32的

     

    其实ddpush的案例很详情了   ,处了这个OnlieService是主要执行的方法,别的是控制电量和Receiver广播通知ddpush启动的代码

    展开全文
  • 在前一篇文章中我们主要分析了AppServer是如何连接到DDPush,并向DDPush推送消息,还没有看过的朋友请移步DDPush开源推送框架源码分析之APPServer到DDPush。 本篇文章主要讲解Client(客户端)如何连接到DDPush...
    在前一篇文章中我们主要分析了AppServer是如何连接到DDPush,并向DDPush推送消息,还没有看过的朋友请移步DDPush开源推送框架源码分析之APPServer到DDPush


    本篇文章主要讲解Client(客户端)如何连接到DDPush,并向DDPush发送消息(主要是心跳包和确认信息),和如何接收APPServer推送给DDPush的消息,本篇文章分析官方推荐的UDP工作模式。


    UDP模式主要涉及到以下几个重要的类:

    1、UdpConnector 监听端口的UDP数据包

    2、Receiver 接受终端消息

    3、Sender 向终端发送消息

    4、Messenger 从Receiver的消息队列中取出消息, 再从内存中查找对应的状态机以及需要发送给终端的消息, 最后加入到Sender的消息队列并由Sender发出去


    一、UdpConnector

    关键方法start()

    public void start() throws Exception{
    		if(antenna != null){
    			throw new Exception("antenna is not null, may have run before");
    		}
    		antenna = DatagramChannel.open();
    		antenna.socket().bind(new InetSocketAddress(port));
    		System.out.println("udp connector port:"+port);
    		//non-blocking
    		antenna.configureBlocking(false);
    		antenna.socket().setReceiveBufferSize(1024*1024*PropertyUtil.getPropertyInt("CLIENT_UDP_BUFFER_RECEIVE"));
    		antenna.socket().setSendBufferSize(1024*1024*PropertyUtil.getPropertyInt("CLIENT_UDP_BUFFER_SEND"));
    		System.out.println("udp connector recv buffer size:"+antenna.socket().getReceiveBufferSize());
    		System.out.println("udp connector send buffer size:"+antenna.socket().getSendBufferSize());
    		
    		
    		this.receiver = new Receiver(antenna);
    		this.receiver.init();
    		this.sender = new Sender(antenna);
    		this.sender.init();
    		
    		this.senderThread = new Thread(sender,"AsynUdpConnector-sender");
    		this.receiverThread = new Thread(receiver,"AsynUdpConnector-receiver");
    		this.receiverThread.start();
    		this.senderThread.start();
    	}
    第6行:绑定一个端口端口,监听此端口的数据包

    第16行:receiver是一个runnable对象,用来接受Client发来的消息

    第19行:sender是一个runnable对象,用来向Client推送消息

    第21-24行:分别启动receiver和sender


    二、Receiver

    第一步:run()方法

    public void run(){
    		while(!this.stoped){
    			try{
    				//synchronized(enQueSignal){
    					processMessage();
    				//	if(mq.isEmpty() == true){
    				//		enQueSignal.wait();
    				//	}
    				//}
    			}catch(Exception e){
    				e.printStackTrace();
    			}catch(Throwable t){
    				t.printStackTrace();
    			}
    		}
    	}
    这是一个while循环,用来不断的接收消息,主要看第5行的processMessage()方法

    第二步:processMessage()方法

    protected void processMessage() throws Exception{
    		address = null;
    		buffer.clear();
    		try{
    			address = this.channel.receive(buffer);
    		}catch(SocketTimeoutException timeout){
    			
    		}
    		if(address == null){
    			try{
    				Thread.sleep(1);
    			}catch(Exception e){
    				
    			}
    			return;
    		}
    		
    		buffer.flip();
    		byte[] swap = new byte[buffer.limit() - buffer.position()];
    		System.arraycopy(buffer.array(), buffer.position(), swap, 0, swap.length);
    
    		ClientMessage m = new ClientMessage(address,swap);
    		
    		enqueue(m);
    		//System.out.println(DateTimeUtil.getCurDateTime()+" r:"+StringUtil.convert(m.getData())+" from:"+m.getSocketAddress().toString());
    
    	}
    第5行:接收数据填充到buffer,因为DatagramChannel设置成非阻塞了,所以此方法不管有无数据都会立即返回,所以第9行会做一个判断

    第19-20:将buffer缓冲区的数据拷贝到swap数据

    第22行:将byte[]数组和Client的address信息封装成ClientMessage对象

    第24行:将ClientMessage对象加入到消息队列,等待处理(Messenger会从此队列取消息)


    三、Sender

    第一步:run()方法

    public void run(){
    		while(!this.stoped){
    			try{
    				synchronized(enQueSignal){
    					while(mq.isEmpty() == true && stoped == false){
    						try{
    							enQueSignal.wait(1);
    						}catch(InterruptedException e){
    							
    						}
    						//System.out.println("sender wake up");
    					}
    					processMessage();
    					
    				}
    			}catch(Exception e){
    				e.printStackTrace();
    			}catch(Throwable t){
    				t.printStackTrace();
    			}
    		}
    	}
    这是一个while循环,用来不断的发送消息,主要看第13行的processMessage()方法

    第二步:processMessage()方法

    protected void processMessage() throws Exception{
    		buffer.clear();
    		ServerMessage pendingMessage = dequeue();
    		if(pendingMessage == null){
    			//Thread.yield();
    			return;
    		}
    		buffer.put(pendingMessage.getData());
    		buffer.flip();
    		channel.send(buffer, pendingMessage.getSocketAddress());
    		//System.out.println(DateTimeUtil.getCurDateTime()+" s:"+StringUtil.convert(pendingMessage.getData())+" to  :"+pendingMessage.getSocketAddress().toString());
    	}
    第3行:从消息发送队列取出一条消息,ServerMessage对象主要包括消息内容和Client地址信息两个属性

    第8行:将消息内容放到缓冲区

    第10行:将消息内容发送给Client
    那么问题来了,Receiver中加入队列的ClientMessage怎么转为ServerMessage并加入到Sender的消息发送队列的呢?这就涉及另外一个重要的角色Messenger


    四、Messenger

    这也是一个实现Runnable接口的对象,所以首先找到run()方法

    第一步:run()方法

    @Override
    	public void run() {
    		this.started = true;
    		
    		while(stoped == false){
    			try{
    				procMessage();
    			}catch(Exception e){
    				e.printStackTrace();
    			}catch(Throwable t){
    				t.printStackTrace();
    			}
    		}
    
    	}
    这是一个while循环,用来不断的发送消息,主要看第7行的procMessage()方法


    第二步:procMessage()方法

    private void procMessage() throws Exception{
    		ClientMessage m = this.obtainMessage();
    		if(m == null){
    			try{
    				Thread.sleep(5);
    			}catch(Exception e){
    				;
    			}
    			return;
    		}
    		// 对终端发布消息
    		this.deliverMessage(m);
    		
    	}
    第2行:从队列取出一条Client发过来的消息,ClientMessage是不是很眼熟?我们看下this.obtainMessage()这个方法 private ClientMessage obtainMessage() throws Exception{
      return connector.receive();
     }
    它又调用了connector的receiver()方法,connector就是UdpConnector对象,那么我们看下UdpConnector的receiver()方法
    public ClientMessage receive() throws Exception {
      return receiver.receive();
     }

    什么?它又调用了receiver的receiver()方法,好吧,绕了半天,原来最终是从receiver的消息队列中取得消息的。

    第12行:处理Client发来的消息,那么我们具体看下deliverMessage(m)这个方法


    第三步、deliverMessage(ClientMessage m)方法

    private void deliverMessage(ClientMessage m) throws Exception{
    		//System.out.println(this.hostThread.getName()+" receive:"+StringUtil.convert(m.getData()));
    		//System.out.println(m.getSocketAddress().getClass().getName());
    		String uuid = m.getUuidHexString();
    		//ClientStatMachine csm = NodeStatus.getInstance().getClientStat(uuid);
    		ClientStatMachine csm = nodeStat.getClientStat(uuid); // 查找内存中的状态机
    		if(csm == null){//
    			csm = ClientStatMachine.newByClientTick(m); // 创建状态机
    			if(csm == null){
    				return;
    			}
    			nodeStat.putClientStat(uuid, csm);
    		}
    		// 查找是否有消息发送给终端
    		ArrayList<ServerMessage> smList = csm.onClientMessage(m);
    		if(smList == null){
    			return;
    		}
    		for(int i = 0; i < smList.size(); i++){
    			ServerMessage sm = smList.get(i);
    			if(sm.getSocketAddress() == null)continue;
    			this.connector.send(sm);
    		}
    		
    	}
    第4行:是一个标准的UUID,用来唯一标识每一个用户

    第6行:根据UUID去内存中查找有没有状态机csm,可以理解为一个在线用户对象

    第7-13行:内存中没有该用户则创建一个并保存

    第15行:根据Client发送过来的消息,判断需不需要回复、是否有离线的消息需要发给此用户,消息封装为ServerMessage并加入到集合,因为可能会有多条消息需要下发

    第22行:将ServerMessage推送给客户端,看到这里,我们不禁有疑问,Sender不是用来给Client推送消息的吗?我们看下this.connector.send(sm);这行代码执行了什么,它是调用UdpConnector对象的send(ServerMessage message)方法,让我们看下这个方法

    public boolean send(ServerMessage message) throws Exception {
    		return sender.send(message);
    		
    	}
    它又调用了Sender对象的send(ServerMessage message)方法,继续跟踪下去

    public boolean send(ServerMessage message){
    		return enqueue(message);
    	}
    看到这里,我们应该能明白了,这个方法的作用是将需要推送的ServerMessage对象加入到Sender的消息队列,Sender的run()方法会从队列去取消息再推送给客户端。


    到此,我们应该明白了UDP模式Client与DDPush的交互流程。好了,本篇文章的讲解也就到此结束了,如有问题,欢迎大家指正!









    展开全文
  • 在好几年前,就已经注意到DDPush这款推送中间件,不过看近来发展也还是停留在V1.0的基础上,不免惋惜!恰好最近正在深入研究Java Socket通信编程,也顺带再看看这款应用。官网地址:http://www.ddpush.net/ 目录 ...
  • DDPush (Dimension Door Push),任意门推送,是一款开源免费的单机千万级实时信息推送服务器,使用Java语言开发,具有简单、稳定、高性能、高容量等特点,适用于互联网、移动互联网、物联网、Android、智能设备、...
  • 这是我写的ddpush使用php在网页端管理推送的一个解决方案。大家可以下载自行修改使用。 我的博客地址 http://blog.csdn.net/brok1n
  • 我这里小小的说一下大多数接触ddpush的人关心的问题。 ddpush 可以用作IOS推送么(这个几乎是问的最多的一个问题) 答: ddpush 的本质。是通过TCP/UDP来建立客户端和服务器端的长连接。然后服务器端向客户端发送...
  • ddpush 学习之路 1 前言

    千次阅读 2015-03-15 15:59:47
    ddpush学习之路首先来说一下。ddpush 是一个使用java编写的开源的 推送 服务器 同时 ddpush的开发者也写了android端的使用demo 。之前也捣鼓了一阵子ddpush弄的云里雾里的。现在准备要开始系统的学习一下 ddpush了。...
  • 关于 ddpush 的 webManager 的说明

    千次阅读 2015-04-25 18:17:06
    我写的这个ddpushWebManager 是我对ddpush的web推送写的一种解决方案。或者说是一种ddpush web推送的解决思路。再次申明:ddpush 不是我写的。 ddpush 的官方网站 http://www.ddpush.net/ddpush 官方 提供了一个...
  • ddpush原理及过程分析

    2015-08-25 16:20:42
    ddpush提供了两种连接方式。UDP 和 TCP 官方说明。 UDP比TCP的同时连接数要多很多倍。所以推荐用UDP的方式。 ddpush是用来做推送的。所以说一下。首先ddpush服务器端建立UDP或者TCP服务器。 然后监听服务器的99...
  • DDPush任意门推送.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • ddpush 学习之路 4 PropertyUtil.java

    千次阅读 2015-03-17 01:47:22
    我们来解析 ddpush的第三个类 PropertyUtil.java 我们现在是解析ddpush的第三个类。这三个类都在ddpush的 org.ddpush.im.util 包中。我查看了一下ddpush的server端的代码。加上两个example类一共只有26个, 我们...
  • ddpush 学习之路 12 Sender.java

    千次阅读 2015-03-28 01:54:48
    我们来学习 ddpush 中的一个UDP服务器的数据发送类。 ddpush 中 给我们提供了两种和服务器的连接方式。一种是UDP 一种是TCP 在ddpush的官方网站上,ddpush的开发者推荐大家使用UDP这种方式来做推送。理由 就是 UDP的...
  • ddpush 学习之路 11 MyUdpClient.java

    千次阅读 2015-03-22 15:14:17
    继续来学习我们的ddpush源代码。这次我们学习ddpush给我们提供的两个example的第二个example MyUdpClient.java 这两个example类在 org.ddpush.im.v1.client.appuser.example 这个包中。下面上被我添加注释的这个类的...
  • ddpush使用

    2018-03-05 16:31:24
    import org.ddpush.im.v1.client.appuser.UDPClientBase; public class Pushclass { public void sendMsg(String toName, String whatYouWantSay) { // 消息内容不能为空 if (whatYouWantSay.trim().equals...
  • ddpush 学习之路 10 MyTcpClient.java

    千次阅读 2015-03-22 15:09:38
    我们接着来学习ddpush的源代码。再ddpush的源代码中。提供了两个example 来为我们讲解如何具体的使用TCPClientBase和UDPClientBase这两个类。前面我们已经吧这两个类学习完了。下面就来学习ddpush中提供的这两个类的...
  • ddpush 学习之路 5 Message.java

    千次阅读 2015-03-18 01:16:29
    我们今天来学习ddpush的地四个类。 Message.java Message.java存放在org.ddpush.im.v1.client.appuser包中今天弄的这个类让我比较费劲。好吧 其实是以前没怎么用过ByteBuffer 今天把 ByteBuffer的api从新看了一遍。...
  • ddpush 学习之路 9 ClientMessage.java

    千次阅读 2015-03-22 14:26:22
    现在我们来学ddpush的 ClientMessage.java 这个类。这个类和上一个 Constant.java 类都是在 org.ddpush.im.v1.node 包中。这两个类比较简单。我看完学习完。就发出来了。好了。下面我们来看 ClientMessage.java 这个...
  • ddpush 学习之路 6 TCPClientBase.java

    千次阅读 2015-03-22 02:22:52
    和上一个类的学习时间间隔了几天。两个原因。第一个原因:这个类,稍微的那么有些复杂。我看、我看、我在看。才基本明白了。第二个原因:我屋里路由器总是掉新在深深的无奈之下。...因为ddpush就是用来服务器和客
  • ddpush 学习之路 2 DateTimeUtil.java

    千次阅读 2015-03-15 16:42:28
    是org.ddpush.im.util包中的 DateTimeUtil.java 来。先上我注释的该类代码,在类注释下面,会有具体的使用代码以及结果public class DateTimeUtil { /** * DateTimeUtil 类中的一个静态常量 * 是用来格式化日期...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 130
精华内容 52
关键字:

ddpush