默认
发表评论 9
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
[已回复] MobileIMSDK android版用服务端向客户端发消息失败
阅读(34957) | 评论(9 收藏 淘帖
使用MobileIMSDK android,用服务端向客户端发消息失败,调用的是ServerLauncherImpl.sendData(0, from_user_id, "json数据",true);
有遇到过的吗?

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

标签:MobileIMSDK

111111.png (47.14 KB, 下载次数: 1694)

111111.png
上一篇:Go语言构建千万级在线的高并发消息推送系统实践(来自360公司)下一篇:信鸽团队原创:一起走过 iOS10 上消息推送(APNS)的坑
推荐方案
评论 9
看样子你改过源码,而且出错的原因很明显,应该是有什么地方改动的不对。

你可以描述一下你大致改动了什么代码,如果能把改动的代码跟原先的代码作一个比对截个图发出来,一看就能明白了。MobileIMSDK官方原版是一定可以用服务端API发送消息给指定客户端的,不然要这个sdk有何用。所以,优先检查你改过的代码
引用:JackJiang 发表于 2017-06-07 12:01
看样子你改过源码,而且出错的原因很明显,应该是有什么地方改动的不对。

你可以描述一下你大致改动了什 ...

这套代码本来是PC上的,现在是把它移到了android上面来,也就是在手机上搭建了这个服务器,肯定是删掉了很多东西的,在看看吧。。。现在也不知道为什么是null。。
引用:JackJiang 发表于 2017-06-07 12:01
看样子你改过源码,而且出错的原因很明显,应该是有什么地方改动的不对。

你可以描述一下你大致改动了什 ...

这个是这样的,我把这个服务端,移植到了Android 上,我们有项目需要用到这个类似的推送。android 上由于没有java.awt.event.ActionEvent  和java.awt.event.ActionListener 的支持,我把这里的东西都注释掉了。
/*
 * Copyright (C) 2016 即时通讯网(52im.net) The MobileIMSDK Project. 
 * All rights reserved.
 * Project URL:[url=https://github.com/JackJiang2011/MobileIMSDK]https://github.com/JackJiang2011/MobileIMSDK[/url]
 *  
 * 即时通讯网(52im.net) - 即时通讯技术社区! PROPRIETARY/CONFIDENTIAL.
 * Use is subject to license terms.
 * 
 * QoS4SendDaemonS2C.java at 2016-2-20 11:26:03, code by Jack Jiang.
 * You can contact author with [url=mailto:jack.jiang@52im.net]jack.jiang@52im.net[/url] or [url=mailto:jb2011@163.com]jb2011@163.com[/url].
 */
package net.openmob.mobileimsdk.server.qos;

//import java.awt.event.ActionEvent;
//import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
//import javax.swing.Timer;

import net.openmob.mobileimsdk.server.ServerLauncher;
import net.openmob.mobileimsdk.server.protocal.Protocal;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QoS4SendDaemonS2C
{
        private static Logger logger = LoggerFactory.getLogger(QoS4SendDaemonS2C.class);

        public static boolean DEBUG = false;

        public static final int CHECH_INTERVAL = 5000;
        public static final int MESSAGES_JUST$NOW_TIME = 2000;
        public static final int QOS_TRY_COUNT = 1;

        private ServerLauncher serverLauncher = null;
        private ConcurrentHashMap<String, Protocal> sentMessages = new ConcurrentHashMap<String, Protocal>();
        private ConcurrentHashMap<String, Long> sendMessagesTimestamp = new ConcurrentHashMap<String, Long>();

        private boolean running = false;
        private boolean _excuting = false;
//        private Timer timer = null;

        private static QoS4SendDaemonS2C instance = null;

        public static QoS4SendDaemonS2C getInstance()
        {
                if (instance == null)
                        instance = new QoS4SendDaemonS2C();
                return instance;
        }

        private QoS4SendDaemonS2C()
        {
                init();
        }

        private void init()
        {
//                this.timer = new Timer(CHECH_INTERVAL, new ActionListener()
//                {
//                        public void actionPerformed(ActionEvent e) {
//                                QoS4SendDaemonS2C.this.run();
//                        }
//                });
        }

        public void run()
        {
                // 极端情况下本次循环内可能执行时间超过了时间间隔,此处是防止在前一
                // 次还没有运行完的情况下又重复执行,从而出现无法预知的错误
                if (!this._excuting)
                {
                        ArrayList<Protocal> lostMessages = new ArrayList<Protocal>();
                        this._excuting = true;
                        try
                        {
                                if (DEBUG) {
                                        logger.debug("【IMCORE】【QoS发送方】=========== 消息发送质量保证线程运行中, 当前需要处理的列表长度为" + this.sentMessages.size() + "...");
                                }

                                for (String key : this.sentMessages.keySet())
                                {
                                        Protocal p = (Protocal)this.sentMessages.get(key);
                                        if ((p != null) && (p.isQoS()))
                                        {
                                                if (p.getRetryCount() >= QOS_TRY_COUNT)
                                                {
                                                        if (DEBUG) {
                                                                logger.debug("【IMCORE】【QoS发送方】指纹为" + p.getFp() + 
                                                                                "的消息包重传次数已达" + p.getRetryCount() + "(最多" + QOS_TRY_COUNT + "次)上限,将判定为丢包!");
                                                        }

                                                        lostMessages.add((Protocal)p.clone());

                                                        remove(p.getFp());
                                                }
                                                else
                                                {
                                                        //### 2015104 Bug Fix: 解决了无线网络延较大时,刚刚发出的消息在其应答包还在途中时被错误地进行重传
                                                        long delta = System.currentTimeMillis() - sendMessagesTimestamp.get(key);
                                                        // 该消息包是“刚刚”发出的,本次不需要重传它哦
                                                        if(delta <= MESSAGES_JUST$NOW_TIME)
                                                        {
                                                                if(DEBUG)
                                                                        logger.warn("【IMCORE】【QoS发送方】指纹为"+key+"的包距\"刚刚\"发出才"+delta
                                                                                +"ms(<="+MESSAGES_JUST$NOW_TIME+"ms将被认定是\"刚刚\"), 本次不需要重传哦.");
                                                        }
                                                        //### 2015103 Bug Fix END
                                                        else
                                                        {
                                                                boolean sendOK = ServerLauncher.sendData(p);

                                                                p.increaseRetryCount();

                                                                if (sendOK)
                                                                {
                                                                        if (DEBUG) {
                                                                                logger.debug("【IMCORE】【QoS发送方】指纹为" + p.getFp() + 
                                                                                                "的消息包已成功进行重传,此次之后重传次数已达" + 
                                                                                                p.getRetryCount() + "(最多" + 1 + "次).");
                                                                        }

                                                                }
                                                                else if (DEBUG) {
                                                                        logger.warn("【IMCORE】【QoS发送方】指纹为" + p.getFp() + 
                                                                                        "的消息包重传失败,它的重传次数之前已累计为" + 
                                                                                        p.getRetryCount() + "(最多" + 1 + "次).");
                                                                }
                                                        }

                                                }
                                        }
                                        else
                                        {
                                                remove(key);
                                        }
                                }
                        }
                        catch (Exception eee)
                        {
                                if (DEBUG) {
                                        logger.warn("【IMCORE】【QoS发送方】消息发送质量保证线程运行时发生异常," + eee.getMessage(), eee);
                                }
                        }
                        if ((lostMessages != null) && (lostMessages.size() > 0))
                        {
                                notifyMessageLost(lostMessages);
                        }

                        this._excuting = false;
                }
        }

        protected void notifyMessageLost(ArrayList<Protocal> lostMessages)
        {
                if ((this.serverLauncher != null) && (this.serverLauncher.getServerMessageQoSEventListener() != null))
                        this.serverLauncher.getServerMessageQoSEventListener().messagesLost(lostMessages);
        }

        public QoS4SendDaemonS2C startup(boolean immediately)
        {
                stop();

//                if (immediately)
//                        this.timer.setInitialDelay(0);
//                else
//                        this.timer.setInitialDelay(CHECH_INTERVAL);
//                
//                this.timer.start();
//                this.running = true;

                return this;
        }

        public void stop()
        {
//                if (this.timer != null) {
//                        this.timer.stop();
//                }

                this.running = false;
        }

        public boolean isRunning()
        {
                return this.running;
        }

        public boolean exist(String fingerPrint)
        {
                return this.sentMessages.get(fingerPrint) != null;
        }

        public void put(Protocal p)
        {
                if (p == null)
                {
                        if (DEBUG)
                                logger.warn("Invalid arg p==null.");
                        return;
                }
                if (p.getFp() == null)
                {
                        if (DEBUG)
                                logger.warn("Invalid arg p.getFp() == null.");
                        return;
                }

                if (!p.isQoS())
                {
                        if (DEBUG)
                                logger.warn("This protocal is not QoS pkg, ignore it!");
                        return;
                }

                if (this.sentMessages.get(p.getFp()) != null)
                {
                        if (DEBUG) {
                                logger.warn("【IMCORE】【QoS发送方】指纹为" + p.getFp() + "的消息已经放入了发送质量保证队列,该消息为何会重复?(生成的指纹码重复?还是重复put?)");
                        }
                }

                // save it
                sentMessages.put(p.getFp(), p);
                // 同时保存时间戳
                sendMessagesTimestamp.put(p.getFp(), System.currentTimeMillis());
        }

        public void remove(String fingerPrint)
        {
                //### 20151129 Bug Fix: 解决了之前错误地在服务端实现本remove方法时
                //        使用了SwingWorker而导致一段时间后一定几率下整个Timer不能正常工作了(OOM)
                try
                {
                        // remove it
                        sendMessagesTimestamp.remove(fingerPrint);
                        Object result = sentMessages.remove(fingerPrint);
                        if(DEBUG)
                                logger.warn("【IMCORE】【QoS发送方】指纹为"+fingerPrint+"的消息已成功从发送质量保证队列中移除(可能是收到接收方的应答也可能是达到了重传的次数上限),重试次数="
                                                +(result != null?((Protocal)result).getRetryCount():"none呵呵."));
                }
                catch (Exception e)
                {
                        if(DEBUG)
                                logger.warn("【IMCORE】【QoS发送方】remove(fingerPrint)时出错了:", e);
                }
                //### 20151129 Bug Fix END 
        }

        public int size()
        {
                return this.sentMessages.size();
        }

        public void setServerLauncher(ServerLauncher serverLauncher)
        {
                this.serverLauncher = serverLauncher;
        }
}

无论如何,这个QoS类也只跟消息送达保证有关,而你的代码是在服务端数据接收时就出错了,所以目前的问题可先不管这个QoS类。像这个空指针错误一定是一个非常明显的低级问题,你把源码里的异常栈打印出来,在Android上是:Log.d(TAG, e) 这样的日志输出就可以
这个不是收数据的时候报错的,是发数据的时候报错的。。。。我看了一下和你源码里面的改动基本上不会影响到这里。日志就是最上面的日志了。
或者我要怎么弄一下日志打印给到你?
06-07 16:00:56.855: D/SencondServer(13477): myIntent===>com.tchip.mid_undock
06-07 16:00:56.881: E/MediaPlayer(13477): Should have subtitle controller already set
06-07 16:00:56.885: E/BaseApplication(13477): action=com.tchip.mid_undock
06-07 16:00:56.903: E/123(13477): ====================================
06-07 16:00:56.905: E/ServerCoreHandler(13477): ------------sendData(Protocal p)------------
06-07 16:00:56.905: E/ServerCoreHandler(13477): ------------sendData(IoSession session, Protocal p)------------(0x00000001: nio datagram, server, /192.168.1.6:51270 => /:::26386)
06-07 16:00:56.912: E/ServerCoreHandler(13477): [IMCORE]exceptionCaught捕获到错了,原因是:null
06-07 16:00:56.913: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:FRD-AL00,cid:10001}/192.168.1.6:51270
06-07 16:00:56.913: I/ServerCoreHandler(13477): [IMCORE]与{uid:FRD-AL00,cid:10001}/192.168.1.6:51270的会话关闭(user_id=10001,loginName=FRD-AL00)了...
06-07 16:00:56.913: E/ServerCoreHandler(13477): [IMCORE]exceptionCaught捕获到错了,原因是:Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference
06-07 16:00:57.018: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:FRD-AL00,cid:10001}/192.168.1.6:51270
06-07 16:00:57.020: W/ServerCoreHandler(13477): [IMCORE]给客户端:{uid:FRD-AL00,cid:10001}/192.168.1.6:51270的数据->{"QoS":false,"dataContent":"{\"message\":\"66666\",\"type\":67}","from":0,"to":10001,"type":2},发送失败![94](此消息可考虑作离线处理哦).
06-07 16:00:57.020: D/DialerFragment(13477): ---onReceive---lastStation===>com.tchip.mid_undock
06-07 16:00:57.046: W/MediaPlayer(13477): mediaplayer went away with unhandled events
06-07 16:00:57.046: E/MediaPlayer(13477): Should have subtitle controller already set
06-07 16:00:58.751: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:null,cid:-1}/192.168.1.6:51270
06-07 16:00:58.751: I/ServerCoreHandler(13477): [IMCORE]与{uid:null,cid:-1}/192.168.1.6:51270的会话建立(sessionCreated)了...
06-07 16:00:58.752: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:null,cid:-1}/192.168.1.6:51270
06-07 16:00:58.752: I/ServerCoreHandler(13477): [IMCORE]与{uid:null,cid:-1}/192.168.1.6:51270的会话(sessionOpened)打开了...
06-07 16:00:58.752: E/ServerCoreHandler(13477): -----
06-07 16:00:58.754: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:null,cid:-1}/192.168.1.6:51270
06-07 16:00:58.754: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:null,cid:-1}/192.168.1.6:51270
06-07 16:00:58.755: W/ServerCoreHandler(13477): [IMCORE]>> 客户端{uid:null,cid:-1}/192.168.1.6:51270尚未登陆,{}处理未继续.
06-07 16:00:58.760: E/ServerCoreHandler(13477): ------------sendData(IoSession session, Protocal p)------------(0x00000002: nio datagram, server, /192.168.1.6:51270 => /:::26386)
06-07 16:01:00.902: E/ServerCoreHandler(13477): -----
06-07 16:01:00.904: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:null,cid:-1}/192.168.1.6:51270
06-07 16:01:00.906: I/ServerCoreHandler(13477): [IMCORE]>> 客户端{uid:null,cid:-1}/192.168.1.6:51270发过来的登陆信息内容是:getLoginName=FRD-AL00|getLoginPsw=88888888
06-07 16:01:00.906: E/ServerCoreHandler(13477): alreadyLogined=false
06-07 16:01:00.906: D/ServerEventListenerImpl(13477): 正在调用回调方法:OnVerifyUserCallBack...(extra=null  lpUserName=FRD-AL00  lpPassword=88888888)
06-07 16:01:00.908: E/ServerCoreHandler(13477): ------------sendData(IoSession session, Protocal p)------------(0x00000002: nio datagram, server, /192.168.1.6:51270 => /:::26386)
06-07 16:01:00.914: D/ServerEventListenerImpl(13477): 正在调用回调方法:OnUserLoginAction_CallBack... userId=10002  userName=FRD-AL00  /192.168.1.6:51270
06-07 16:01:00.914: E/123(13477): ipString=/192.168.1.6:51270   ipStr=192.168.1.6
06-07 16:01:00.927: E/ServerCoreHandler(13477): -----
06-07 16:01:00.930: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:FRD-AL00,cid:10002}/192.168.1.6:51270
06-07 16:01:00.930: I/ServerCoreHandler(13477): >> 收到客户端{uid:FRD-AL00,cid:10002}/192.168.1.6:51270的通用数据发送请求.
06-07 16:01:00.930: D/ServerCoreHandler(13477): 【IMCORE】【QoS机制_S2C】收到10002发过来的指纹为f5fc0d43-2c0a-4cdf-88dd-1b398c837fad的应答包.
06-07 16:01:03.974: E/ServerCoreHandler(13477): -----
06-07 16:01:03.977: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:FRD-AL00,cid:10002}/192.168.1.6:51270
06-07 16:01:03.977: E/ServerCoreHandler(13477): ------------sendData(Protocal p)------------
06-07 16:01:03.978: E/ServerCoreHandler(13477): ------------sendData(IoSession session, Protocal p)------------(0x00000002: nio datagram, server, /192.168.1.6:51270 => /:::26386)
06-07 16:01:07.047: E/ServerCoreHandler(13477): -----
06-07 16:01:07.050: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:FRD-AL00,cid:10002}/192.168.1.6:51270
06-07 16:01:07.050: E/ServerCoreHandler(13477): ------------sendData(Protocal p)------------
06-07 16:01:07.051: E/ServerCoreHandler(13477): ------------sendData(IoSession session, Protocal p)------------(0x00000002: nio datagram, server, /192.168.1.6:51270 => /:::26386)
06-07 16:01:07.175: D/SencondServer(13477): myIntent===>com.tchip.mid_ondock
06-07 16:01:07.205: E/MediaPlayer(13477): Should have subtitle controller already set
06-07 16:01:07.208: E/BaseApplication(13477): action=com.tchip.mid_ondock
06-07 16:01:07.214: D/DialerFragment(13477): ---onReceive---lastStation===>com.tchip.mid_ondock
06-07 16:01:07.258: E/MediaPlayer(13477): Should have subtitle controller already set
06-07 16:01:09.972: E/ServerCoreHandler(13477): -----
06-07 16:01:09.976: E/ServerCoreHandler(13477): ------clientInfoToString---{uid:FRD-AL00,cid:10002}/192.168.1.6:51270
06-07 16:01:09.977: E/ServerCoreHandler(13477): ------------sendData(Protocal p)------------
06-07 16:01:09.978: E/ServerCoreHandler(13477): ------------sendData(IoSession session, Protocal p)------------(0x00000002: nio datagram, server, /192.168.1.6:51270 => /:::26386)
这日志根本看不出什么,你要找到出问题的那段代码,针对出问题的代码再作分析。
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部