package com.easysocket.connection.connect; 
 | 
  
 | 
import android.os.Handler; 
 | 
  
 | 
import com.easysocket.EasySocket; 
 | 
import com.easysocket.callback.SuperCallBack; 
 | 
import com.easysocket.config.EasySocketOptions; 
 | 
import com.easysocket.connection.action.SocketAction; 
 | 
import com.easysocket.connection.action.SocketStatus; 
 | 
import com.easysocket.connection.dispatcher.CallbackResponseDispatcher; 
 | 
import com.easysocket.connection.dispatcher.SocketActionDispatcher; 
 | 
import com.easysocket.connection.heartbeat.HeartManager; 
 | 
import com.easysocket.connection.iowork.IOManager; 
 | 
import com.easysocket.connection.reconnect.AbsReconnection; 
 | 
import com.easysocket.entity.SocketAddress; 
 | 
import com.easysocket.entity.basemsg.SuperCallbackSender; 
 | 
import com.easysocket.exception.NotNullException; 
 | 
import com.easysocket.interfaces.config.IConnectionSwitchListener; 
 | 
import com.easysocket.interfaces.conn.IConnectionManager; 
 | 
import com.easysocket.interfaces.conn.ISocketActionListener; 
 | 
import com.easysocket.utils.LogUtil; 
 | 
import com.easysocket.utils.Utils; 
 | 
  
 | 
import java.io.IOException; 
 | 
import java.util.concurrent.ExecutorService; 
 | 
import java.util.concurrent.Executors; 
 | 
import java.util.concurrent.atomic.AtomicInteger; 
 | 
  
 | 
/** 
 | 
 * Author:Alex 
 | 
 * Date:2019/5/29 
 | 
 * Note:socket连接的超类 
 | 
 */ 
 | 
public abstract class SuperConnection implements IConnectionManager { 
 | 
  
 | 
    /** 
 | 
     * 连接状态,初始值为断开连接 
 | 
     */ 
 | 
    protected final AtomicInteger connectionStatus = new AtomicInteger(SocketStatus.SOCKET_DISCONNECTED); 
 | 
    /** 
 | 
     * 连接线程 
 | 
     */ 
 | 
    private ExecutorService connExecutor; 
 | 
    /** 
 | 
     * socket地址信息 
 | 
     */ 
 | 
    protected SocketAddress socketAddress; 
 | 
    /** 
 | 
     * socket行为分发器 
 | 
     */ 
 | 
    private SocketActionDispatcher actionDispatcher; 
 | 
    /** 
 | 
     * 重连管理器 
 | 
     */ 
 | 
    private AbsReconnection reconnection; 
 | 
    /** 
 | 
     * io管理器 
 | 
     */ 
 | 
    private IOManager ioManager; 
 | 
    /** 
 | 
     * 心跳管理器 
 | 
     */ 
 | 
    private HeartManager heartManager; 
 | 
    /** 
 | 
     * 配置信息 
 | 
     */ 
 | 
    protected EasySocketOptions socketOptions; 
 | 
    /** 
 | 
     * socket回调消息的分发器 
 | 
     */ 
 | 
    private CallbackResponseDispatcher callbackResponseDispatcher; 
 | 
    /** 
 | 
     * 连接切换的监听 
 | 
     */ 
 | 
    private IConnectionSwitchListener connectionSwitchListener; 
 | 
  
 | 
    public SuperConnection(SocketAddress socketAddress) { 
 | 
        this.socketAddress = socketAddress; 
 | 
        actionDispatcher = new SocketActionDispatcher(this, socketAddress); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public void subscribeSocketAction(ISocketActionListener iSocketActionListener) { 
 | 
        actionDispatcher.subscribe(iSocketActionListener); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public void unSubscribeSocketAction(ISocketActionListener iSocketActionListener) { 
 | 
        actionDispatcher.unsubscribe(iSocketActionListener); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public synchronized IConnectionManager setOptions(EasySocketOptions socketOptions) { 
 | 
        if (socketOptions == null) return this; 
 | 
  
 | 
        this.socketOptions = socketOptions; 
 | 
  
 | 
        if (ioManager != null) 
 | 
            ioManager.setOptions(socketOptions); 
 | 
  
 | 
        if (heartManager != null) 
 | 
            heartManager.setOptions(socketOptions); 
 | 
  
 | 
        if (callbackResponseDispatcher != null) 
 | 
            callbackResponseDispatcher.setSocketOptions(socketOptions); 
 | 
  
 | 
        // 更改了重连器 
 | 
        if (reconnection != null && !reconnection.equals(socketOptions.getReconnectionManager())) { 
 | 
            reconnection.detach(); 
 | 
            reconnection = socketOptions.getReconnectionManager(); 
 | 
            reconnection.attach(this); 
 | 
        } 
 | 
        return this; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public EasySocketOptions getOptions() { 
 | 
        return socketOptions; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public synchronized void connect() { 
 | 
  
 | 
        if (connectionStatus.get() == SocketStatus.SOCKET_DISCONNECTING) { 
 | 
            new Handler().postDelayed(() -> { 
 | 
                LogUtil.d("---> socket>>connect>>正在断开连接,延时一秒執行重连"); 
 | 
                connect(); 
 | 
            }, 1000); // 延时1秒 
 | 
            return; 
 | 
        } 
 | 
        LogUtil.d("---> socket开始连接"); 
 | 
        if (socketAddress.getIp() == null) { 
 | 
            throw new NotNullException("请检查是否设置了IP地址"); 
 | 
        } 
 | 
        // 正在连接 
 | 
        connectionStatus.set(SocketStatus.SOCKET_CONNECTING); 
 | 
  
 | 
        // 心跳管理器 
 | 
        if (heartManager == null) { 
 | 
            heartManager = new HeartManager(this, actionDispatcher); 
 | 
        } 
 | 
  
 | 
        // 重连管理器 
 | 
        if (reconnection != null) { 
 | 
            reconnection.detach(); 
 | 
        } 
 | 
        reconnection = socketOptions.getReconnectionManager(); 
 | 
        if (reconnection != null) { 
 | 
            reconnection.attach(this); 
 | 
        } 
 | 
  
 | 
        // 开启分发消息线程 
 | 
        if (actionDispatcher != null) { 
 | 
            actionDispatcher.startDispatchThread(); 
 | 
        } 
 | 
        // 开启连接线程 
 | 
        if (connExecutor == null || connExecutor.isShutdown()) { 
 | 
            // 核心线程数为0,非核心线程数可以有Integer.MAX_VALUE个,存活时间为60秒,适合于在不断进行连接的情况下,避免重复创建和销毁线程 
 | 
            connExecutor = Executors.newCachedThreadPool(); 
 | 
            // 执行连接任务 
 | 
        } 
 | 
        connExecutor.execute(connTask); 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public synchronized void disconnect(boolean isNeedReconnect) { 
 | 
        // 判断当前socket的连接状态 
 | 
        if (connectionStatus.get() == SocketStatus.SOCKET_DISCONNECTED) { 
 | 
            return; 
 | 
        } 
 | 
        // 正在重连中 
 | 
        if (isNeedReconnect && reconnection.isReconning()) { 
 | 
            return; 
 | 
        } 
 | 
        // 正在断开连接 
 | 
        connectionStatus.set(SocketStatus.SOCKET_DISCONNECTING); 
 | 
  
 | 
        // 开启断开连接线程 
 | 
        String info = socketAddress.getIp() + " : " + socketAddress.getPort(); 
 | 
        Thread disconnThread = new DisconnectThread(isNeedReconnect, "disconn thread:" + info); 
 | 
        disconnThread.setDaemon(true); 
 | 
        disconnThread.start(); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 断开连接线程 
 | 
     */ 
 | 
    private class DisconnectThread extends Thread { 
 | 
        boolean isNeedReconnect; // 当前连接的断开是否需要自动重连 
 | 
  
 | 
        public DisconnectThread(boolean isNeedReconnect, String name) { 
 | 
            super(name); 
 | 
            this.isNeedReconnect = isNeedReconnect; 
 | 
        } 
 | 
  
 | 
        @Override 
 | 
        public void run() { 
 | 
            try { 
 | 
                // 关闭io线程 
 | 
                if (ioManager != null) 
 | 
                    ioManager.closeIO(); 
 | 
                // 关闭回调分发器线程 
 | 
                if (callbackResponseDispatcher != null) 
 | 
                    callbackResponseDispatcher.shutdownThread(); 
 | 
                // 关闭连接线程 
 | 
                if (connExecutor != null && !connExecutor.isShutdown()) { 
 | 
                    connExecutor.shutdown(); 
 | 
                    connExecutor = null; 
 | 
                } 
 | 
                // 关闭连接 
 | 
                closeConnection(); 
 | 
                actionDispatcher.dispatchAction(SocketAction.ACTION_DISCONNECTION, new Boolean(isNeedReconnect)); 
 | 
                if (!isNeedReconnect){ 
 | 
                    heartManager.stopHeartbeat(); 
 | 
                } 
 | 
                LogUtil.d("---> 关闭socket连接"); 
 | 
                connectionStatus.set(SocketStatus.SOCKET_DISCONNECTED); 
 | 
            } catch (IOException e) { 
 | 
                // 断开连接发生异常 
 | 
                e.printStackTrace(); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    // 连接任务 
 | 
    private Runnable connTask = new Runnable() { 
 | 
        @Override 
 | 
        public void run() { 
 | 
            try { 
 | 
                openConnection(); 
 | 
            } catch (Exception e) { 
 | 
                // 连接异常 
 | 
                e.printStackTrace(); 
 | 
                LogUtil.d("---> socket连接失败"); 
 | 
                connectionStatus.set(SocketStatus.SOCKET_DISCONNECTED); 
 | 
                // 第二个参数指需要重连 
 | 
                actionDispatcher.dispatchAction(SocketAction.ACTION_CONN_FAIL, new Boolean(true)); 
 | 
  
 | 
            } 
 | 
        } 
 | 
    }; 
 | 
  
 | 
    /** 
 | 
     * 连接成功 
 | 
     */ 
 | 
    protected void onConnectionOpened() { 
 | 
        LogUtil.d("---> socket连接成功"); 
 | 
        openSocketManager(); 
 | 
        connectionStatus.set(SocketStatus.SOCKET_CONNECTED); 
 | 
        actionDispatcher.dispatchAction(SocketAction.ACTION_CONN_SUCCESS); 
 | 
    } 
 | 
  
 | 
    // 开启socket相关管理器 
 | 
    private void openSocketManager() { 
 | 
        if (callbackResponseDispatcher == null) 
 | 
            callbackResponseDispatcher = new CallbackResponseDispatcher(this); 
 | 
        if (ioManager == null) { 
 | 
            ioManager = new IOManager(this, actionDispatcher); 
 | 
        } 
 | 
        ioManager.startIO(); 
 | 
  
 | 
        // 启动相关线程 
 | 
        callbackResponseDispatcher.engineThread(); 
 | 
        ioManager.startIO(); 
 | 
    } 
 | 
  
 | 
    // 切换了主机IP和端口 
 | 
    @Override 
 | 
    public synchronized void switchHost(SocketAddress socketAddress) { 
 | 
        if (socketAddress != null) { 
 | 
            SocketAddress oldAddress = this.socketAddress; 
 | 
            this.socketAddress = socketAddress; 
 | 
  
 | 
            if (actionDispatcher != null) 
 | 
                actionDispatcher.setSocketAddress(socketAddress); 
 | 
            // 切换主机 
 | 
            if (connectionSwitchListener != null) { 
 | 
                connectionSwitchListener.onSwitchConnectionInfo(this, oldAddress, socketAddress); 
 | 
            } 
 | 
        } 
 | 
  
 | 
    } 
 | 
  
 | 
    public void setOnConnectionSwitchListener(IConnectionSwitchListener listener) { 
 | 
        connectionSwitchListener = listener; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public boolean isConnectViable() { 
 | 
        // 当前socket是否处于可连接状态 
 | 
        return Utils.isNetConnected(EasySocket.getInstance().getContext()) && connectionStatus.get() == SocketStatus.SOCKET_DISCONNECTED; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public int getConnectionStatus() { 
 | 
        return connectionStatus.get(); 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 打开连接 
 | 
     * 
 | 
     * @throws IOException 
 | 
     */ 
 | 
    protected abstract void openConnection() throws Exception; 
 | 
  
 | 
    /** 
 | 
     * 关闭连接 
 | 
     * 
 | 
     * @throws IOException 
 | 
     */ 
 | 
    protected abstract void closeConnection() throws IOException; 
 | 
  
 | 
    /** 
 | 
     * 发送bytes数据 
 | 
     * 
 | 
     * @param bytes 
 | 
     * @return 
 | 
     */ 
 | 
    private IConnectionManager sendBytes(byte[] bytes) { 
 | 
        if (ioManager == null || connectionStatus.get() != SocketStatus.SOCKET_CONNECTED) { 
 | 
            LogUtil.w("sendBytes错误-----ioManager为null或者connectionStatus状态不为已连接"); 
 | 
            return this; 
 | 
        } 
 | 
        ioManager.sendBytes(bytes); 
 | 
        return this; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 消息回调主要处理超时消息 
 | 
     * @param callBack 
 | 
     */ 
 | 
    @Override 
 | 
    public void onCallBack(SuperCallBack callBack) { 
 | 
        callbackResponseDispatcher.addSocketCallback(callBack); 
 | 
    } 
 | 
  
 | 
  
 | 
    @Override 
 | 
    public synchronized IConnectionManager upBytes(byte[] bytes) { 
 | 
        sendBytes(bytes); 
 | 
        return this; 
 | 
    } 
 | 
  
 | 
    @Override 
 | 
    public synchronized IConnectionManager upCallbackMessage(SuperCallbackSender sender) { 
 | 
        callbackResponseDispatcher.checkCallbackSender(sender); 
 | 
        // 发送 
 | 
        sendBytes(sender.pack()); 
 | 
        return this; 
 | 
    } 
 | 
  
 | 
  
 | 
    @Override 
 | 
    public HeartManager getHeartManager() { 
 | 
        return heartManager; 
 | 
    } 
 | 
} 
 |