Android P实现Tcp socket心跳包机制 保证socket断开重连

知识共享许可协议 版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文 (Creative Commons

本文的例子是客户端的例子,只有客户端的代码。

服务器端作为数据接收方,客户端作为数据发送方。

Socket通信断开的情况:

  • 网络断开,导致socket通信断开;
  • 服务端程序崩溃或者服务端没有启动,导致socket连接失败;

客户端在SocketService中实现。

public class SocketService extends Service {
    private static final String TAG = "SocketService";

    private static Socket mSocket;
    //Hearbeat time
    private long mSendTime = 0L;

    //Heart rate
    private static final long HEART_BEAT_RATE = 3 * 1000;

    //For Heartbeat
    private Handler mHandler = new Handler();

	@Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    
    @Override
    public void onCreate() {
        super.onCreate();
        //开启Tcp socket连接线程
        new InitSocketThread().start();
	}
	
    @Override
    public void onDestroy() {
        super.onDestroy();
        //释放连接资源
        releaseLastSocket();
        //移除心跳包线程
        mHandler.removeCallbacks(mHeartbeatRunnable);
    }

    //Start Heartbeat thread
    private Runnable mHeartbeatRunnable = new Runnable() {
        @Override
        public void run() {
            if (System.currentTimeMillis() - mSendTime >= HEART_BEAT_RATE) {
            	//发送心跳包
            	//发送成功表示连接正常
            	//发送失败表示socket连接断开,重启socket连接线程进行连接
            	//sendHeartbeatPackage为发送数据
                boolean isSuccess = sendHeartbeatPackage();
                if (!isSuccess) {
                    //release last socket
                    mHandler.removeCallbacks(mHeartbeatRunnable);
                    releaseLastSocket();

                    //Restart to create tcp connection
                    new InitSocketThread().start();
                }
            }

			//循环发送心跳包,3s一次
            mHandler.postDelayed(this, HEART_BEAT_RATE);
        }
    };

	//客户端连接socket的代码
    class InitSocketThread extends Thread {
        @Override
        public void run() {
            super.run();
            try {
                //Start heartbeat thread
                //先启动心跳包线程,否则new socket连接失败报错直接到catch中
                mHandler.postDelayed(mHeartbeatRunnable, HEART_BEAT_RATE);
                mSocket = new Socket("127.0.0.1", 9898);
            } catch (IOException e) {
            	//注意不能使用e.printStackTrace()打印异常
            	//使用e.printStackTrace()异常报错会导致程序报错退出,从而无法进行重连
                //e.printStackTrace();
                Log.i(TAG,"new Socket,IOException");
            }
        }
    }

	//发送心跳包
	//心跳包的数据格式自己定义,服务端收到心跳包可以不予处理
	//这里的心跳包格式:A66A0A00000000FF
    public boolean sendHeartbeatPackage() {
		//连接成功的情况下才发送心跳包
        if( mSocket == null || mSocket.isClosed() || mSocket.isOutputShutdown() ){
            return false;
        }
        final byte buffer[] = new byte[8];
        buffer[0] = (byte)0xA6;
        buffer[1] = 0x6A;
        buffer[2] = 0x0A;
        buffer[3] = 0x00;
        buffer[4] = 0x00;
        buffer[5] = 0x00;
        buffer[6] = 0x00;
        buffer[7] = (byte)0xFF;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    OutputStream os = mSocket.getOutputStream();
                    os.write(buffer);
                    os.flush();
                } catch (IOException e) {
                	//发送出错 断开socket然后进行重连
                	releaseLastSocket();
                    e.printStackTrace();
                }
            }
        }).start();
		
		//计算发送心跳包的时间
        mSendTime = System.currentTimeMillis();
        
        Log.i(TAG,"sendHeartbeatPackage,Heartbeats...");
        return true;
    }

    /**
     * Release socket connetion
     */
    private void releaseLastSocket() {
        try {
            if (null != mSocket) {
                if (!mSocket.isClosed()) {
                    mSocket.close();
                }
                mSocket = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

服务启动了,开启心跳包线程,心跳频率为3s,心跳包发送失败后表示连接已经断开了。连接断开后,执行重连线程。

猜你喜欢

转载自blog.csdn.net/Sunxiaolin2016/article/details/93969198