请选择 进入手机版 | 继续访问电脑版

默认
发表评论 7
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
[已回复] RainbowChat如何更新到最新的MobileIMSDK 5.0
服务后端,android ,ios端如何更新,请大家分享一下经验,谢谢

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

上一篇:[已回复] 反馈RainbowChat ios app4.0线上版本聊天UI的界面显示问题下一篇:[已解决] 求助 im app在vivio-x9手机上,闪屏结束后崩溃的问题
推荐方案
评论 7
到Github下载最新MobileIMSDK v5,替换jar包:https://github.com/JackJiang2011/MobileIMSDK
签名: 《零基础IM开发入门(三):什么是IM系统的可靠性?》http://www.52im.net/thread-3182-1-1.html
引用:JackJiang 发表于 2020-09-22 13:55
到Github下载最新MobileIMSDK v5,替换jar包:https://github.com/JackJiang2011/MobileIMSDK

很多api都变了,有替换的说明吗?
引用:tang280 发表于 2020-09-22 14:27
很多api都变了,有替换的说明吗?

MobileIMSDK 5.0跟老版不兼容的地方,主要是有些类名、方法名、包名进行了规范和重构。除此之外,API调用没有任何变化。

大致的升级情况是这样的。

对于java或Android端,从老版升级到v5.0时:

  • 1)包名由原先的net.openmob,重构为net.x52im;
  • 2)所有带有UDP字样的类名,都去掉了UDP 3个字母,比如:原LocalUDPSocketProvicer.java,新版里是“LocalSocketProvicer.java”;
  • 3)所有带有UDP字样的方法名,都去掉了UDP 3个字母;

对于服务端,重构的内容主要是ServerEvenLisner类:
具体的新版API是这样:http://docs.52im.net/extend/docs/api/mobileimsdk/server_tcp/net/x52im/mobileimsdk/server/event/ServerEventListener.html
这个类里的方法,除了方法名跟老版不一样,其它都是一一对应的,你看看方法名、参数,就能对应上了。

其它如果有我没有提到的,你升级替换为新版jar包时报错的话,就把错误贴出来,我告诉你怎么适配升级就好了,没有复杂的事情!
签名: 《零基础IM开发入门(三):什么是IM系统的可靠性?》http://www.52im.net/thread-3182-1-1.html
博主你好,我在升级过程中有一些疑问, 具体如下:

  • 1、目的:从UDP协议升级到TCP
  • 2、环境信息:项目用的是RainbowChat V6.0, MINA版本
  • 3、升级步骤:
       - 1)下载最新的MobileIMSDKServer.jar 5.0版本、
       - 2)依次替换了响应的Jar包、
       - 3)将openmob找不到的类包名换成 x52im,操作下来大部分的报错都已解决。

下面说下遇到的几个问题:

第一个问题:在原来的ChatServerLauncher类里引入了的
//import net.x52im.mobileimsdk.server.bridge.QoS4ReciveDaemonC2B;
//import net.x52im.mobileimsdk.server.bridge.QoS4SendDaemonB2C;
2个类无法在找到了。目前看下来这2个类就只是设置了下debug而已,所以目前是先屏蔽了此代码。

第二个问题:启动端口问题,在升级之前,启动的时候 使用ChatServerLauncher.PORT = BaseConf.getInstance().getIM_SERVER_UDP_LISTENNING_PORT(); 来从配置文件里读取的端口,升级后PORT属性不存在了,阅读了下代码,应该是转移到GatewayTCP和GatewayUDP类里了。所以GatewayTCP.PORT = BaseConf.getInstance().getIM_SERVER_TCP_LISTENNING_PORT();就直接在启动到时候重新给响应到PORT赋值了,另外增加了ChatServerLauncher.supportedGateways = 2; 启动TCP的配置,请问这样操作是正确的吗?

第三个问题:关于ServerEventListener,因为之前用的是MINA,所以在ServerEventListener的接口方法里,参数类型是IoSession,而升级后,用的是NETTY, 所以是否就将IoSession换成Channel就可以了呢?

第四个问题:关于LocalSendHelper,发送数据,升级前是有返回boolean,升级后返回void了,并在入参里增加了MBObserver来处理发送成功和失败的逻辑,帮忙判断下理解点是否正确呢?

上面的几点主要是围绕项目能启动所遇到的一些疑问。另外一个是一个升级后新旧版本兼容方案的问题,能给个建议如何做兼容方案吗?
引用:yml 发表于 2020-10-10 23:33
博主你好,我在升级过程中有一些疑问, 具体如下:

我仔细看了你的升级过程,包括正常升级过程,和问题的处理方法,基本都是正确的,没有隐患。

不过,为了保险起见,我专门帮你针对MobileIMSDK -v5的升级,准备了关键地方的升级示例,你参考一下。

针对第一、二问题:你的处理没有毛病,以下是我为你准备的最佳实践样例,你就照这个改就对了。
package com.x52im.rainbowchat.im;

import java.io.IOException;

import com.x52im.rainbowchat.BaseConf;

import net.x52im.mobileimsdk.server.ServerLauncher;
import net.x52im.mobileimsdk.server.event.MessageQoSEventListenerS2C;
import net.x52im.mobileimsdk.server.event.ServerEventListener;
import net.x52im.mobileimsdk.server.network.Gateway;
import net.x52im.mobileimsdk.server.network.GatewayTCP;
import net.x52im.mobileimsdk.server.network.GatewayUDP;
import net.x52im.mobileimsdk.server.processor.BridgeProcessor;
import net.x52im.mobileimsdk.server.qos.QoS4ReciveDaemonC2S;
import net.x52im.mobileimsdk.server.qos.QoS4SendDaemonS2C;

/**
 * IM服务启动入口类。
 * 
 * @author Jack Jiang([url=http://www.52im.net/space-uid-1.html]http://www.52im.net/space-uid-1.html[/url])
 * @version 1.0
 */
public class ChatServerLauncher extends ServerLauncher
{
    private static ChatServerLauncher instance = null;
        
    public static ChatServerLauncher getInstance() throws IOException
    {
        if(instance == null)
         {
            // 设置UDP网络监听端口(如果需修改此端口号,请前往配置文件中修改)
            GatewayUDP.PORT = BaseConf.getInstance().getIM_SERVER_UDP_LISTENNING_PORT();
            // 设置TCP网络监听端口(如果需修改此端口号,请前往配置文件中修改)
            GatewayTCP.PORT = BaseConf.getInstance().getIM_SERVER_TCP_LISTENNING_PORT();
                        
            // 设置服务端支持UDP、TCP协议情况(默认同时支持两种,如需修改请前往配置文件中修改)
            boolean isSupportUDP = BaseConf.getInstance().getIM_SERVER_UDP_SUPPORT();
            boolean isSupportTCP = BaseConf.getInstance().getIM_SERVER_TCP_SUPPORT();
            ServerLauncher.supportedGateways = (isSupportUDP? Gateway.SUPPORT_UDP:0) | (isSupportTCP? Gateway.SUPPORT_TCP:0);
                        
             instance = new ChatServerLauncher();

            // 开启或关闭Debug日志输出
            QoS4SendDaemonS2C.getInstance().setDebugable(true);
            QoS4ReciveDaemonC2S.getInstance().setDebugable(false);
//          QoS4SendDaemonB2C.getInstance().setDebugable(true);
//          QoS4ReciveDaemonC2B.getInstance().setDebugable(false);
                                                
            // 关闭与Web端的消息互通桥接器 (TODO:如需与Web端IM互通,请配置此项为ture,否则请设为false)
            ServerLauncher.bridgeEnabled = BaseConf.getInstance().getIM_BRIDGE_ENABLED();
             // 跨服桥接器MQ的URI(本参数只在ServerLauncher.bridgeEnabled为true时有意义)
            BridgeProcessor.IMMQ_URI = BaseConf.getInstance().getIM_BRIDGE_MQ_URI();
        }
         return instance; 
    }
        
    public ChatServerLauncher() throws IOException
    {
        super();
    }
        
    /**
     * 初始化回调处理事件监听器。
     * <p>
     * 本类重写 {[url=home.php?mod=space&uid=5196]@link[/url] #initListeners()}方法,以实现应用层的回调监听器以便实现自定义业务
     * 逻辑,可以设置的回调监听器有: {@link #setServerEventListener(ServerEventListener)}
     * 和 {@link #setServerMessageQoSEventListener(MessageQoSEventListenerS2C)}。
     */
    @Override
    protected void initListeners()
    {
        // ** 设置回调
        this.setServerEventListener(ChatServerEventListener.getInstance());
    }
        
    /**
      * 重写父类的本方法,方便直接使用本工程中的ChatServerEventListener(即ServerEventListener
      * 接口的实现类。
      * 
      * {@inheritDoc}
      */
    @Override
    public ChatServerEventListener getServerEventListener()
    {
        return (ChatServerEventListener)serverCoreHandler.getServerEventListener();
    }
}

针对第3个问题:你的处理也完全是对的!

针对第4个问题:看你的描述,也正确。为了保险起见,我也专门为你准备了一个示例,你就以此为最佳实践,用就对了!
比如,好友上线通知这个例子,在升级MobileIMSDK-v5前,它是这样写的:
SendResult code = new SendResult(false, null);
// 遍历在线好友列表,看看该好友是否在线
if(liveUsers.containsKey(friend_user_uid))
{
    code = MessageHelper.sendOnlineMessage(friend_user_uid, userId);

    if(code.isCode())
        LoggerFactory.getLog().debug("[RBChat]》登陆用户"+userId+"向它的好友"+friend_user_uid+"/"+friend_user_mail+"发送上线通知成功!");
    else
        LoggerFactory.getLog().debug("[RBChat]》登陆用户"+userId+"向它的好友"+friend_user_uid+"/"+friend_user_mail+"发送上线通知失败,错误code="+code);
}
else
{
    LoggerFactory.getLog().debug("[RBChat]》登陆用户"+userId+"的好友"+friend_user_uid+"/"+friend_user_mail+"不在线,无需发送上线通知。");
}

在升级MobileIMSDK-v5后,这样改写就对了:
// 遍历在线好友列表,看看该好友是否在线
if(liveUsers.containsKey(friend_user_uid))
{
    // 指令发送结果观察者(因为通信底层netty是异步通知数据发送结果的)
    SendResultObserver sendResultObserver = new SendResultObserver(){
    @Override
    public void update(boolean code, Protocal p) {
        if(code)
            LoggerFactory.getLog().debug("[RBChat]》登陆用户"+userId+"向它的好友"+friend_user_uid+"/"+friend_user_mail+"发送上线通知成功!");
        else
            LoggerFactory.getLog().debug("[RBChat]》登陆用户"+userId+"向它的好友"+friend_user_uid+"/"+friend_user_mail+"发送上线通知失败,错误code="+code);
        }
    };
    MessageHelper.sendOnlineMessage(friend_user_uid, userId, sendResultObserver);
}
else
{
    LoggerFactory.getLog().debug("[RBChat]》登陆用户"+userId+"的好友"+friend_user_uid+"/"+friend_user_mail+"不在线,无需发送上线通知。");
}

最后,关于你说的与旧版本兼容问题:这个因为MobileIMSDK新版只保留了Netty实现(原先的MINA版已经不维护了),而Netty的API是完全异步风格,为了匹配它的代码最佳实践,只能这样去改,强行用同步调用,会影响它的性能,得不偿失。除此之外,已经尽可能最大限度保持兼容性了,一些方法命名明显不合理的地方,新版里也只能忍痛改了,不然历史包袱越来越多,代码就越来越恶心了。
签名: 《零基础IM开发入门(三):什么是IM系统的可靠性?》http://www.52im.net/thread-3182-1-1.html
博主你好,在升级到 MobileIMSDKServer.jar 5.0版本的时候,之前有写过一个用户在移动端只能在一个设备上登录,下面的代码是之前的逻辑。
public void putUser(String user_id, IoSession session)
        {
                if(onlineSessions.containsKey(user_id))
                {
                        logger.debug("[IMCORE]【注意】用户id="+user_id+"已经在在线列表中了,session也是同一个吗?"
                                        +(onlineSessions.get(user_id).hashCode() == session.hashCode()));
                        
                        // 踢出老的session
                        logOutOldSession(user_id, session);
                        
                }
                
                onlineSessions.put(user_id, session);
                
                __printOnline();// just for debug
        }
        
        /**
         * 一个用户,不可以登录多个端
         * @param user_id
         * @param session
         */
        private void logOutOldSession(String user_id, IoSession session) {
                IoSession oldSession = onlineSessions.get(user_id);
                if (oldSession == null) {
                        logger.debug("logOutOldSession oldSession is null user_id: "+user_id+"------------------->");
                        return;
                }
                
                // 相同的端登录 不T
                if (oldSession.hashCode() == session.hashCode()) {
                        logger.debug("logOutOldSession session hashcode equals user_id: "+user_id+"------------------->");
                        return;
                }
                
                try {
                        // 给之前端session发送 logout消息
                        /** 下线通知报文头 */
                        int LOG_OUT = 99;
                        logger.debug("logOutOldSession send logout message user_id: "+user_id+"------------------->");
                        LocalSendHelper.sendData(oldSession, ProtocalFactory.createCommonData("logout", "0", user_id, false, null, LOG_OUT));
                        oldSession.removeAttribute(OnlineProcessor.USER_ID_IN_SESSION_ATTRIBUTE);
                        oldSession.close(true);
                } catch (Exception e) {
                        logger.debug("logOutOldSession send data exception hashcode equals user_id: "+user_id+"------------------->");
                        e.printStackTrace();
                }
                
        }

核心的逻辑是:
LocalSendHelper.sendData(oldSession, ProtocalFactory.createCommonData("logout", "0", user_id, false, null, LOG_OUT));
oldSession.removeAttribute(OnlineProcessor.USER_ID_IN_SESSION_ATTRIBUTE);
oldSession.close(true);

因为之前是在MINA版本的,而现在换成了Netty了,能帮忙给下这3行的代码用Netty的写法吗?

引用:yml 发表于 2020-10-12 21:28
博主你好,在升级到 MobileIMSDKServer.jar 5.0版本的时候,之前有写过一个用户在移动端只能在一个设备上登 ...

你的疑问,总结一下,应该是你不知道Netty里的Channel,如何实现MINA里的IoSession中设置、移除、读取自定义会话属性的能力。

其实,Netty的很多方面设计跟Mina是一脉相承的,只是写法不同而已

比如:

netty里设置属性的代码是这样的:
session.attr(OnlineProcessor.USER_ID_IN_SESSION_ATTRIBUTE_ATTR).set(loginInfo.getLoginUserId());
具体你参考MobileIMSDK的这个类里的真实代码实现(你同时也可以去对比一下MINA版)。

netty里移除属性的代码是这样的:
session.attr(OnlineProcessor.USER_ID_IN_SESSION_ATTRIBUTE_ATTR).set(null);
具体你参考MobileIMSDK的这个类里的真实代码实现(你同时也可以去对比一下MINA版)。

netty里读取属性的代码是这样的(比如下面这段MobileIMSDK中的例子):
        public static String getUserIdFromSession(Channel session)
        {
                Object attr = null;
                if(session != null)
                {
                        attr = session.attr(USER_ID_IN_SESSION_ATTRIBUTE_ATTR).get();
                        if(attr != null)
                                return (String)attr;
                }
                return null;
        }
具体你参考MobileIMSDK的这个类里的真实代码实现(你同时也可以去对比一下MINA版)。
签名: 《零基础IM开发入门(三):什么是IM系统的可靠性?》http://www.52im.net/thread-3182-1-1.html
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部