socket心跳检测和重连小demo

        有时候我们的程序要求socket一直保持连接,并且希望在socket断开以后能够重新连接,这个时候就需要用到心跳机制,所谓心跳机制,最简单的做法就是客户端每隔一段时间向服务端发送数据包,为了节约资源我们很多时候发送空数据就好,如果数据不能发送成功说明socket已经断开,这个时候就需要根据具体需求释放资源和重新连接了。

        下面给出一个简单的小demo 

 /**
     * 连接服务端
     */
    private void connectToServer() {
        Thread connectThread = new Thread(new Runnable() {
            public void run() {
                try {
                    mSocket = new Socket();
                    mSocket.connect(
                            new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));

                    Log.e(TAG, "连接成功  " + SOCKET_HOST);
                    mDataOutputStream = new DataOutputStream(
                            mSocket.getOutputStream());
                    
                    // 开启线程负责读取服务端数据
                    mReadThread = new SocketReadThread();
                    mReadThread.start();
                    
                    // 心跳检测,检测socket是否连接
                    mHandler.postDelayed(mHeartBeatRunnable, HEART_BEAT_RATE);
                } catch (UnknownHostException e) {
                    Log.e(TAG, "连接失败  ");
                    e.printStackTrace();
                } catch (IOException e) {
                    Log.e(TAG, "连接失败  ");
                    e.printStackTrace();
                }
            }
        });
        connectThread.start();
    }

         上述方法负责创建新的socket实例和开启心跳检测,其中比较重要的代码是
          mHandler.postDelayed(mHeartBeatRunnable, HEART_BEAT_RATE);
          这里的HEART_BEAT_RATE是一个int常量,表示心跳间隔,mHeartBeatRunnableze则负责心跳检测

// 心跳机制
    private SocketReadThread mReadThread;
    private static final long HEART_BEAT_RATE = 4 * 1000;
    private long sendTime = 0L;
    private Runnable mHeartBeatRunnable = new Runnable() {

        @Override
        public void run() {
            if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {//每隔4秒检测一次
                boolean isSuccess = sendHeartBeatMsg("");
                if (!isSuccess) {
                    Log.i(TAG, "连接已断开,正在重连……");
                    mHandler.removeCallbacks(mHeartBeatRunnable);// 移除线程,重连时保证该线程已停止上次调用时的工作
                    mReadThread.release();//释放SocketReadThread线程资源
                    releaseLastSocket();
                    connectToServer();// 再次调用connectToServer方法,连接服务端
                }
            }
            mHandler.postDelayed(this, HEART_BEAT_RATE);
        }
    };
    /**
     * 发送心跳包
     * 
     * @param msg
     * @return
     */
    public boolean sendHeartBeatMsg(String msg) {
        if (null == mSocket) {
            return false;
        }
        try {
            if (!mSocket.isClosed() && !mSocket.isOutputShutdown()) {
                String message = msg + "\r\n";
                mDataOutputStream.write(message.getBytes());
                mDataOutputStream.flush();
                sendTime = System.currentTimeMillis();
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

        上述方法是心跳检测的主要方法,调用sendHeartBeatMsg()发送数据到服务端,该方法稍后给出。如果检测到连接断开,则释放各种资源,重新连接。如果连接没有断开则继续检测,非常简单的逻辑

/**
  * 断开连接
  *
  */
    private void releaseLastSocket() {
        try {
            if (null != mSocket) {
                if (!mSocket.isClosed()) {
                    mSocket.close();
                }
            }
            mSocket = null;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

         最后给出SocketReadThread线程,这个线程负责读取服务端发送过来的数据,和心跳机制无关,但在心跳机制中重连处理时,一定要释放它的资源。

public class SocketReadThread extends Thread {

        private static final String TAG = "SocketThread";
        private volatile boolean mStopThread = false;
        public void release() {
            mStopThread = true;
            releaseLastSocket();
        }
        @Override
        public void run() {
            DataInputStream mInputStream = null;
            try {
                mInputStream = new DataInputStream(mSocket.getInputStream());
                Logger.d(TAG, "SocketThread running!");
                while (!mStopThread) { 
                    String resultStr = mInputStream.readUTF();
                    handleStringMsg(resultStr);
                }
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    mSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                if (mInputStream != null) {
                    try {
                        mInputStream.close();
                        mInputStream = null;
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }


  • 10
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值