左晓为主开发手持机充值管理机
zuoxiao
2023-11-14 5a843ba11b991722f8f2af386f0e546e2769f7c3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package com.easysocket.connection.reconnect;
 
import android.os.Handler;
import android.os.HandlerThread;
 
import com.easysocket.entity.SocketAddress;
import com.easysocket.interfaces.conn.IConnectionManager;
import com.easysocket.utils.LogUtil;
 
/**
 * Author:Alex
 * Date:2019/5/28
 * Note:默认重连器
 */
public class DefaultReConnection extends AbsReconnection {
    /**
     * 最大连接失败次数,超过可以切换到备用的服务器地址
     */
    private static final int MAX_CONNECTION_FAILED_TIMES = 10;
    /**
     * 连接失败的次数
     */
    private int connectionFailedTimes = 0;
    /**
     * 重连间隔不能小于10秒,为了避免全部客户端socket在同一时间连接服务端,间隔时间需要上下浮动50%
     */
    private long reconnectTimeDelay = 10 * 1000;
    /**
     * 重连线程
     */
    private HandlerThread handlerThread;
    /**
     * 实现延时任务的 handler
     */
    private Handler handler;
 
    public DefaultReConnection() {
    }
 
    @Override
    public synchronized void attach(IConnectionManager iConnectionManager) {
        super.attach(iConnectionManager);
        if (reconnectTimeDelay < connectionManager.getOptions().getConnectTimeout()) {
            reconnectTimeDelay = connectionManager.getOptions().getConnectTimeout();
        }
    }
 
    /**
     * 重连任务
     */
    private final Runnable RcConnTask = new Runnable() {
        @Override
        public void run() {
            LogUtil.d("---> 执行重连");
            if (isDetach) {
                shutDown();
                return;
            }
            // 是否可连接的
            if (!connectionManager.isConnectViable()) {
                LogUtil.d("当前条件不允许连接");
                // 尝试再次重连
                handler.postDelayed(RcConnTask, (long) (reconnectTimeDelay * (Math.random() + 0.5)));
                return;
            }
            // 重连
            connectionManager.connect();
        }
    };
 
    /**
     * 进行重连
     */
    private void reconnect() {
        if (handlerThread == null) {
            handlerThread = new HandlerThread("re_conn");
            handlerThread.start();
            handler = new Handler(handlerThread.getLooper());
        }
        LogUtil.d("重连间隔时间-->" + reconnectTimeDelay * (Math.random() + 0.5));
        handler.postDelayed(RcConnTask, (long) (reconnectTimeDelay * (Math.random() + 0.5)));
    }
 
 
    // 关闭重连线程
    private void shutDown() {
        if (handlerThread != null && handlerThread.isAlive()) {
            handlerThread.quit();
            handlerThread = null;
            handler = null;
        }
    }
 
    @Override
    public boolean equals(Object o) {
        // getClass返回Class类型的对象,比较它们的类型对象是否==,其实是比较它们是否为同一个Class创建的对象
        if (o == null || getClass() != o.getClass()) return false;
        return true;
    }
 
    @Override
    public void onSocketConnSuccess(SocketAddress socketAddress) {
        // 连接成功关闭重连线程
        shutDown();
    }
 
    @Override
    public void onSocketConnFail(SocketAddress socketAddress, boolean isNeedReconnect) {
        // 不需要重连,则关闭重连线程
        if (!isNeedReconnect) {
            shutDown();
            return;
        }
        connectionFailedTimes++;
 
        // 如果大于最大连接次数并且有备用host,则轮流切换两个host
        if (connectionFailedTimes > MAX_CONNECTION_FAILED_TIMES && socketAddress.getBackupAddress() != null) {
            connectionFailedTimes = 0; // 归零
            SocketAddress backupAddress = socketAddress.getBackupAddress();
            SocketAddress nowAddress = new SocketAddress(socketAddress.getIp(), socketAddress.getPort());
            backupAddress.setBackupAddress(nowAddress);
            if (connectionManager.isConnectViable()) {
                connectionManager.switchHost(backupAddress);
                // 切换主机地址,重新连接
                reconnect();
            }
        } else {
            reconnect();
        }
 
    }
 
    @Override
    public void onSocketDisconnect(SocketAddress socketAddress, boolean isNeedReconnect) {
        // 是否需要重连
        if (!isNeedReconnect) {
            shutDown();
            return;
        }
        reconnect();
    }
 
    @Override
    public boolean isReconning() {
        return handlerThread != null && handlerThread.isAlive();
    }
 
}