New file |
| | |
| | | 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) {
|
| | |
|
| | | }
|
| | | }
|
| | | }
|