mina 心跳 时间间隔 失效 和 心包,断线重连的问题

mina 心跳 时间间隔 失效


重连的时候有时候 会导致 时间间隔 失效,重新设置了

keepAliveFilter

也不行,

日志

I/KeepAliveFilter: 间隔时间是1

I/KeepAliveFilter: message sent5465-6041 msg= ping
I/KeepAliveFilter: message write5465-6041
I/KeepAliveFilter: 间隔时间是1
I/KeepAliveFilter: message sent5465-6041 msg= ping
I/KeepAliveFilter: message write5465-6041
I/KeepAliveFilter: 间隔时间是1

I/KeepAliveFilter: message sent5465-6041 msg= ping


 \mina_push\src\main\java\org\apache\mina\filter\keepalive\KeepAliveFilter.java


    @Override
    public void messageSent(IoFilter.NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
        Object message = writeRequest.getMessage();
        Log.i(this.getClass().getSimpleName(),"间隔时间是" + requestInterval);
        Log.i(this.getClass().getSimpleName(), "message sent"+android.os.Process.myPid()+'-'+android.os.Process.myTid() + " msg= " + message);
//        if (!isKeepAliveMessage(session, message)) {
        nextFilter.messageSent(session, writeRequest);
//        }
    }
其中的属性是


private volatile int requestInterval;

private volatile int requestTimeout;

估计是 volatile 导致的


有文章提到


方法1.不可行  synchronize

如何解决volatile的线程安全问题

      解决线程安全问题,不要忘了开篇时候说道的原子性,多线程会有问题,我们是否可以让它实现原子性的操作??当然可以,就是我们的synchronize关键字,在多个线程对同一个变量进行访问时,做一下控制,只让一个线程来操作,这样就不会出现线程安全问题;最典型的操作:

     单例模式中的双重校验!

    到这里就基本结束了,不知道小编的这些见解有没有帮你解答心中的疑惑呢?



方法二  可行,判断下  equestInterval,如果<30  >100 设置为60 即可


    @Override
    public void messageSent(IoFilter.NextFilter nextFilter, IoSession session, WriteRequest writeRequest) throws Exception {
        Object message = writeRequest.getMessage();
        Log.i(this.getClass().getSimpleName(),"间隔时间是" + requestInterval);
        // modied by yanggg 18 04 17
        if(requestInterval < 10 || requestInterval>100){
            requestInterval = 60;
            requestTimeout  = 30;
        }
        Log.i(this.getClass().getSimpleName(), "message sent"+android.os.Process.myPid()+'-'+android.os.Process.myTid() + " msg= " + message);
//        if (!isKeepAliveMessage(session, message)) {
        nextFilter.messageSent(session, writeRequest);
//        }
    }


======测试结果=======

I/KeepAliveFilter: message write2899-3343

I/KeepAliveFilter: 间隔时间是1
I/KeepAliveFilter: message sent2899-3343 msg= ping
I/KeepAliveFilter: message write2899-3343
I/KeepAliveFilter: 间隔时间是60
I/KeepAliveFilter: message sent2899-3343 msg= ping


===========================================================




第二个问题 。断线重连的方式 2种


第一种重连的方式

       //      断线重连回调拦截器
        connector.getFilterChain().addFirst("reconnection", new IoFilterAdapter() {
            @Override
            public void sessionClosed(NextFilter nextFilter, IoSession ioSession) throws Exception {
                for(;;){
                    try{
                        Thread.sleep(8000);
                        // 因为是多线程 有可能其他线程已经重新连接了
                        // TODO 有时候 重连后ping的时间间隔会变成很短,估计是重连了2个连接导致的错误
                        if (!session.isConnected()){

                            //有时候心跳的设置会丢失
                            //初始化心跳
                            //if (keepAliveFilter == null) {

                           // }
                            //keepAliveFilter = new KeepAliveFilter(new ClientKeepAliveMessageFactoryImp(),
                           //         IdleStatus.READER_IDLE,
                           //         KeepAliveRequestTimeoutHandler.DEAF_SPEAKER,
                           //         heartBeatInterval,
                           //         Config.KEEP_ALIVE_RESPONSE_TIMEOUT);
                           // Log.i(TAG, "心跳间隔重新设置为" + heartBeatInterval + "超时时间:" + Config.KEEP_ALIVE_RESPONSE_TIMEOUT);

                            //替换掉原来的
                            connector.getFilterChain()
                                    .replace("keepalive", keepAliveFilter);

                            ConnectFuture future = connector.connect();
                            future.awaitUninterruptibly();// 等待连接创建成功
                            session = future.getSession();// 获取会话
                            if(session.isConnected()){
                                Log.i(TAG,"reconnection 断线重连["+ connector.getDefaultRemoteAddress().getHostName() +":"+ connector.getDefaultRemoteAddress().getPort()+"]成功");
                                break;
                            }
                        }

                    }catch(Exception ex){
                        Log.i(TAG, "reconnection 重连服务器登录失败,3秒再连接一次:"  + ex.getMessage());


                    }
                }
            }
        });


第二种方式
connector.addListener(new IoListener() {
            @Override
            public void sessionDestroyed(IoSession arg0) throws Exception {
                for (;;) {
                    try {
                        Thread.sleep(9000);
                        //因为是多线程 有可能其他线程已经重新连接了
                        if (!session.isConnected()){
                            ConnectFuture future = connector.connect();
                            future.awaitUninterruptibly();// 等待连接创建成功
                            session = future.getSession();// 获取会话
                            if (session.isConnected()) {
                                Log.i(TAG,"addListener IoListener  断线重连[" + connector.getDefaultRemoteAddress().getHostName() + ":" + connector.getDefaultRemoteAddress().getPort() + "]成功");
                                break;
                            }
                        }
                    } catch (Exception ex) {
                        Log.i(TAG,"addListener IoListener 重连服务器登录失败,3秒再连接一次:" + ex.getMessage());
                    }
                }
            }
        });

package com.andy.mina_push.nat;

/**
 * Created by win on 2018/4/15.
 */
import org.apache.mina.core.service.IoService;
import org.apache.mina.core.service.IoServiceListener;
import org.apache.mina.core.session.IdleStatus;
import org.apache.mina.core.session.IoSession;

public class IoListener implements IoServiceListener{
    @Override
    public void serviceActivated(IoService arg0) throws Exception {
        // TODO Auto-generated method stub
    }
    @Override
    public void serviceDeactivated(IoService arg0) throws Exception {
        // TODO Auto-generated method stub
    }
    @Override
    public void serviceIdle(IoService arg0, IdleStatus arg1) throws Exception {
        // TODO Auto-generated method stub
    }
    @Override
    public void sessionCreated(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub
    }

    @Override
    public void sessionClosed(IoSession session) throws Exception {

    }

    @Override
    public void sessionDestroyed(IoSession arg0) throws Exception {
        // TODO Auto-generated method stub
    }
}



阅读更多

没有更多推荐了,返回首页