默认
发表评论 32
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
引用:kelefun 发表于 2017-07-17 09:39
你好,你实现功能了吗?能否贴个示例代码?

没实现呢,发生了奇怪的事情
签名: 该会员没有填写今日想说内容.
引用:JackJiang 发表于 2017-07-18 15:52
解决了吗?

[INFO] - [15:51:43.512][IMCORE]toSession==null >> id=0的用户尝试发给客户端yangqj的消息:str={}因接收方的id已不在线,此次实时发送没有继续(此消息应考虑作离线处理哦). | (LocalSendHelper^sendData:86)
[INFO] - [15:51:46.511][IMCORE]toSession==null >> id=0的用户尝试发给客户端yangqj的消息:str={}因接收方的id已不在线,此次实时发送没有继续(此消息应考虑作离线处理哦). | (LocalSendHelper^sendData:86)
[INFO] - [15:51:49.511][IMCORE]toSession==null >> id=0的用户尝试发给客户端yangqj的消息:str={}因接收方的id已不在线,此次实时发送没有继续(此消息应考虑作离线处理哦). | (LocalSendHelper^sendData:86)
[INFO] - [15:51:52.515][IMCORE]toSession==null >> id=0的用户尝试发给客户端yangqj的消息:str={}因接收方的id已不在线,此次实时发送没有继续(此消息应考虑作离线处理哦). | (LocalSendHelper^sendData:86)
[INFO] - [15:51:55.514][IMCORE]toSession==null >> id=0的用户尝试发给客户端yangqj的消息:str={}因接收方的id已不在线,此次实时发送没有继续(此消息应考虑作离线处理哦). | (LocalSendHelper^sendData:86)在另一个设备重登陆的时候,为什么要调用完这5次,才会再次调用public void putUser(String user_id, IoSession session) ,在上面全部调用完前登陆的话,会把自己给T下来,但是等上面5次重发送结束之后,互踢就一切正常了
签名: 该会员没有填写今日想说内容.
引用:tiandao 发表于 2017-07-18 15:48
public void putUser(String user_id, IoSession session)
        {
                if(onlineSessio ...

互踢解决:  第一步:        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()));
                    try {
                        IoSession oldsession = onlineSessions.get(user_id);
                        logger.debug("-->发送结果:"+LocalSendHelper.sendData(oldsession,ProtocalFactory.createCommonData(
                                        "logout", "0", user_id, false, null, -1)));
                        oldsession.close(true);
                    } catch (Exception e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                    }
                    // TODO 同一账号的重复登陆情况可在此展开处理逻辑
            }

            onlineSessions.put(user_id, session);

            __printOnline();// just for debug
    }  第二步:public void sessionClosed(IoSession session) throws Exception
    {
            String user_id = OnlineProcessor.getUserIdFromSession(session);
            logger.info("[IMCORE]与"+ServerToolKits.clientInfoToString(session)+"的会话关闭(user_id="+user_id+")了...");
            if(user_id != null)
            {
                    logger.info("[是否相同]"+OnlineProcessor.getInstance().getOnlineSession(user_id)+session);
                    if(OnlineProcessor.getInstance().getOnlineSession(user_id).hashCode() == session.hashCode())
                            OnlineProcessor.getInstance().removeUser(user_id);
                    
                    if(serverEventListener != null)
                            serverEventListener.onUserLogoutAction_CallBack(user_id, null, session);
                    else
                            logger.debug("[IMCORE]>> 客户端"+ServerToolKits.clientInfoToString(session)+"的会话被系统close了,但回调对象是null,没有进行回调.");
            }
            else
            {
                    logger.warn("[IMCORE]【注意】客户端"+ServerToolKits.clientInfoToString(session)+"的会话被系统close了,但它里面没有存放user_id,这个会话是何时建立的?");
            }
    }
修改ServerCoreHandler.java文件上面这个函数
OnlineProcessor.getInstance().removeUser(user_id);
改为
                    if(OnlineProcessor.getInstance().getOnlineSession(user_id).hashCode() == session.hashCode())
                            OnlineProcessor.getInstance().removeUser(user_id);

签名: 该会员没有填写今日想说内容.
引用:JackJiang 发表于 2017-07-18 15:52
解决了吗?

我这样的处理方式 可以 吗?
@Override
        public int onVerifyUserCallBack(String userId, String token, String extra, IoSession session) {
                //返回1026代表用户名不存在,返回1027代表密码不正确,返回1028代表此用户已经登录了不允许再登录了。
                User user=userService.findByName(userId);
                if(user==null) {
                        return 1026;
                }
                user=userService.findByNameAndPwd(userId, token);
                if(user==null) {
                        return 1027;
                }
                IoSession ioSession=OnlineProcessor.getInstance().getOnlineSessions().get(userId);
                if(ioSession!=null) {
                        return 1028;
                }
                return 0;
        }
引用:吴佳同 发表于 2017-11-16 11:19
我这样的处理方式 可以 吗?
@Override
        public int onVerifyUserCallBack(String userId, String toke ...

你按照你的逻辑实现就可以了
引用:JackJiang 发表于 2017-11-16 11:31
你按照你的逻辑实现就可以了

在网络出现断线后 框架会自动重连
当重连的时候,有可能再次调用 onVerifyUserCallBack方法,
再次调用 这个方法时,有可能ioSession 还不是null,
按照我的写法 虽然可以达到同一账号只能登录在一个设备上,但有可能造成账号断线后无法自动重连登录。

引用:JackJiang 发表于 2017-11-16 11:31
你按照你的逻辑实现就可以了

如果我不做任何 处理,
当一个账号在多个设备上登录时,会出现什么情况?
框架 会出现什么问题?
引用:吴佳同 发表于 2017-11-16 13:43
在网络出现断线后 框架会自动重连
当重连的时候,有可能再次调用 onVerifyUserCallBack方法,
再次调用 ...

它自动重连的时候,因为之前已经踢掉了其它设备上登陆的端,所以重连时只有这一个客户端存在,没有理由不能自动重连啊。你逻辑不要乱。
下面是我根据 jack的回复 ,写的代码 ,大家 看下 有没有什么问题?
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()));
                        // TODO 同一账号的重复登陆情况可在此展开处理逻辑
                        IoSession oldSession=onlineSessions.get(user_id);
                        if(oldSession!=session) {
                                //当同一账号 在多个设备上登录时,会执行这里的代码,发消息给该账号之前登录的设备,通知它“你的账号在其他设备上登录了,你被踢出去了”,在客户端收到这样类型的消息后,需要调用ClientCoreSDK.release()方法。
                                ServerToUserMessage serverToUserMessage=new ServerToUserMessage();
                                serverToUserMessage.setType(5);
                                try {
                                        LocalSendHelper.sendData("0", user_id, new Gson().toJson(serverToUserMessage),false,0);
                                        Thread.sleep(10000);
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
                onlineSessions.put(user_id, session);
                __printOnline();// just for debug
        }
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()));
                        // TODO 同一账号的重复登陆情况可在此展开处理逻辑
                        IoSession oldSession=onlineSessions.get(user_id);
                        if(oldSession!=session) {
                                //当同一账号 在多个设备上登录时,会执行这里的代码,发消息给该账号之前登录的设备,通知它“你的账号在其他设备上登录了,你被踢出去了”,在客户端收到这样类型的消息后,需要调用ClientCoreSDK.release()方法。
                                ServerToUserMessage serverToUserMessage=new ServerToUserMessage();
                                serverToUserMessage.setType(5);
                                try {
                                        LocalSendHelper.sendData("0", user_id, new Gson().toJson(serverToUserMessage),false,0);
                                        LocalSendHelper.sendData("0", user_id, new Gson().toJson(serverToUserMessage),false,0);
                                        LocalSendHelper.sendData("0", user_id, new Gson().toJson(serverToUserMessage),false,0);
                                        //Thread.sleep(5000);
                                        oldSession.setAttribute(OnlineProcessor.USER_ID_IN_SESSION_ATTRIBUTE, null);
                                        oldSession.close(true);
                                       
                                } catch (Exception e) {
                                        e.printStackTrace();
                                }
                        }
                }
                onlineSessions.put(user_id, session);
                __printOnline();// just for debug
        }
       
不知道群主现在最新的4.*版本,同一个id 重复登录,踢掉前一台设备,这个逻辑还是在onLineProcessor 里面执行吗?
我跟着看了此贴的回复,貌似他们在这儿T之前设备(对应之前的session)的时候,之前的客户端收到被踢,调用退出逻辑,这个退出逻辑,这个是退出逻辑是直接 让客户端直接rlease (调用ClientCoreSDK.getInstance().release();)呢,还是发送一条 退出命令给服务器呢?仅仅是 rlease 就行了吧?
引用:dahai2070 发表于 2019-06-17 10:52
不知道群主现在最新的4.*版本,同一个id 重复登录,踢掉前一台设备,这个逻辑还是在onLineProcessor 里面执 ...

客户端收到被踢指令后,只需要管好自已的事,比如release,服务端怎么断开那是服务端的逻辑,不需要客户端来决定,不然就涉及安全问题了。

另外,我在这个帖子里回复了有关互踢的思路,可以参考一下《[已回复] 求教同一账号、不同设备、同时登陆强制下线的优化方法

请问下,最新版本的sdk,加入了互踢的功能了吗
签名: 哈哈哈
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部