wjc
2023-06-28 14de918a79943e4961b09fa01ed320c6cad41f2e
HDLLinkLocalSdk/src/main/java/com/hdl/sdk/link/socket/TcpSocketBoot.java
New file
@@ -0,0 +1,281 @@
package com.hdl.sdk.link.socket;
import android.text.TextUtils;
import androidx.collection.ArrayMap;
import com.hdl.sdk.link.common.utils.LogUtils;
import com.hdl.sdk.link.common.utils.ThreadToolUtils;
import com.hdl.sdk.link.socket.client.IClient;
import com.hdl.sdk.link.socket.client.IHeartbeat;
import com.hdl.sdk.link.socket.listener.SendListener;
import com.hdl.sdk.link.socket.annotation.ConnectStatus;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingDeque;
/**
 * Created by Tong on 2021/9/26.
 * Tcp/Udp 启动器
 */
public class TcpSocketBoot {
    private ExecutorService connectThread;
    private ExecutorService sendThread;
    private ExecutorService receiveThread;
    private ExecutorService heartbeatThread;
    private final IClient client;
    private IHeartbeat iHeartbeat;
    public void SetHeartbeat(IHeartbeat iHeartbeat){
        this.iHeartbeat=iHeartbeat;
    }
    /**
     * 当前接收到数据的时间
     */
    private  long time=System.currentTimeMillis();
    /**
     * tcp是否已经连接
     */
    private boolean connected=false;
    public IClient getClient() {
        return client;
    }
    public boolean isConnected() {
        return connected;
    }
    private final BlockingQueue<SocketRequest> mMessageQueue = new LinkedBlockingDeque<>();
    private final ArrayMap<String, SendListener> sendMap = new ArrayMap<>();
    public  TcpSocketBoot(IClient client) {
        TCP_SOCKET_BOOT_LIST.add(this);
        this.client = client;
        initConnectThread();
        initReceiveThread();
        initSendThread();
        initHeartbeat();
    }
    /**
     * 记录所有SocketBoot
     */
    final static List<TcpSocketBoot> TCP_SOCKET_BOOT_LIST = new ArrayList();
    /**
     * 根据IP地址及端口获取当前socketBoot
     * @param ipAddress
     * @param port
     * @return
     */
    public static TcpSocketBoot getByEndPoint(String ipAddress, int port){
        if(ipAddress==null){
            return  null;
        }
        for(TcpSocketBoot tcpSocketBoot : TCP_SOCKET_BOOT_LIST){
            if(ipAddress.equals(tcpSocketBoot.getClient().getOptions().getIp())&& tcpSocketBoot.getClient().getOptions().getPort()==port)
            {
                return tcpSocketBoot;
            }
        }
        return  null;
    }
    /**
     * 连接tcp,内部维护掉,可以不用开放外部,根据这个业务我特性处理好
     */
    private synchronized void connect() {
        try {
            LogUtils.i("TCP连接:"+this.getClient().getOptions().getIp());
            client.onConnectStatus(ConnectStatus.CONNECTING);
//            Thread.sleep(700);
            client.connect();
            LogUtils.i("TCP连接成功:"+this.getClient().getOptions().getIp());
            connected=true;
            client.onConnectStatus(ConnectStatus.CONNECTED);
        }catch(Exception e) {
            LogUtils.e(e.getMessage());
        }
    }
    /**
     * 初始化发送线程,只需要初始化一次
     */
    private void initSendThread() {
        if (sendThread == null) {
            sendThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            sendThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            if(connected==false){
                                Thread.sleep(100);
                                continue;
                            }
                            SocketRequest socketRequest = mMessageQueue.take();
                            final String action = socketRequest.getAction();
                            try {
                                client.sendMsg(socketRequest.getData());
                                if (!TextUtils.isEmpty(action)) {
                                    SendListener sendListener = sendMap.get(action);
                                    if (sendListener != null) {
                                        sendListener.onSucceed();
                                    }
                                }
                            } catch (Exception e) {
                                connected = false;
                                LogUtils.e("发送失败:" + e.getMessage());
                                if (!TextUtils.isEmpty(action)) {
                                    SendListener sendListener = sendMap.get(action);
                                    if (sendListener != null) {
                                        sendListener.onError();
                                    }
                                }
                            }
                        } catch (Exception e) {
                            LogUtils.e("发送失败1:" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 初始化接收线程,只需要初始化一次
     */
    public void initReceiveThread() {
        if (receiveThread == null) {
            receiveThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            receiveThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            if (connected) {
                                //读取数据
                                client.onHandleResponse();
                                time= System.currentTimeMillis();
                            } else {
                                try {
                                    Thread.sleep(1000);
                                } catch (Exception ee) {
                                }
                            }
                        } catch (Exception e) {
                            connected = false;
                            LogUtils.e("接收数据线程异常" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 初始化重新连接线程
     */
    private void initConnectThread() {
        if (connectThread == null) {
            connectThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            //一定时间检测一次连接情况,没有连接就执行连接,连接统一由这里维护
            connectThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            if (!connected) {
                                reconect();
                            }
                            Thread.sleep(5*1000);
                        } catch (Exception e) {
                            LogUtils.e("定时连接线程异常:" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 初始化重新心跳线程
     */
    private void initHeartbeat() {
        if (heartbeatThread == null) {
            heartbeatThread = ThreadToolUtils.getInstance().newFixedThreadPool(1);
            heartbeatThread.execute(new Runnable() {
                @Override
                public void run() {
                    while (true) {
                        try {
                            //5秒
                            if (connected && 5 * 1000 < (System.currentTimeMillis() - time)) {
                                time = System.currentTimeMillis();
                                //心跳检测
                                if (iHeartbeat != null)
                                    iHeartbeat.heartbeat();
                            }
                            Thread.sleep(10);
                        } catch (Exception e) {
                            LogUtils.e("定时心跳检测网关异常:" + e.getMessage());
                        }
                    }
                }
            });
        }
    }
    /**
     * 重新连接
     */
    private void reconect() {
        disconnect();
        connect();
    }
    /**
     * 发送无需回调
     * @param msg 发送的数据
     */
    public void sendMsg(byte[] msg) {
        sendMsg(msg, null);
    }
    /**
     * @param listener 一般情况无需监听
     */
    public void sendMsg(byte[] msg, SendListener listener) {
        try {
            SocketRequest request = new SocketRequest(msg);
            if (listener != null && !TextUtils.isEmpty(request.getAction())) {
                sendMap.put(request.getAction(), listener);
            }
            mMessageQueue.put(request);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 关闭连接
     */
    private synchronized void disconnect() {
        try {
            client.disconnect();
            //断开连接
            client.onConnectStatus(ConnectStatus.DISCONNECT);
        } catch (Exception e) {
        }
    }
}