socket心跳检测和重连小demo

转载自: http://blog.csdn.net/u011791526/article/details/53536403java


有时候咱们的程序要求socket一直保持链接,而且但愿在socket断开之后可以从新链接,这个时候就须要用到心跳机制,所谓心跳机制,最简单的作法就是客户端每隔一段时间向服务端发送数据包,为了节约资源咱们不少时候发送空数据就好,若是数据不能发送成功说明socket已经断开,这个时候就须要根据具体需求释放资源和从新链接了。socket

        下面给出一个简单的小demo ide

  1. /** 
  2.     * 链接服务端 
  3.     */  
  4.    private void connectToServer() {  
  5.        Thread connectThread = new Thread(new Runnable() {  
  6.            public void run() {  
  7.                try {  
  8.                    mSocket = new Socket();  
  9.                    mSocket.connect(  
  10.                            new InetSocketAddress(SOCKET_HOST, SOCKET_PORT));  
  11.   
  12.                    Log.e(TAG, "链接成功  " + SOCKET_HOST);  
  13.                    mDataOutputStream = new DataOutputStream(  
  14.                            mSocket.getOutputStream());  
  15.                      
  16.                    // 开启线程负责读取服务端数据  
  17.                    mReadThread = new SocketReadThread();  
  18.                    mReadThread.start();  
  19.                      
  20.                    // 心跳检测,检测socket是否链接  
  21.                    mHandler.postDelayed(mHeartBeatRunnable, HEART_BEAT_RATE);  
  22.                } catch (UnknownHostException e) {  
  23.                    Log.e(TAG, "链接失败  ");  
  24.                    e.printStackTrace();  
  25.                } catch (IOException e) {  
  26.                    Log.e(TAG, "链接失败  ");  
  27.                    e.printStackTrace();  
  28.                }  
  29.            }  
  30.        });  
  31.        connectThread.start();  
  32.    }  

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

  1. // 心跳机制  
  2.     private SocketReadThread mReadThread;  
  3.     private static final long HEART_BEAT_RATE = 4 * 1000;  
  4.     private long sendTime = 0L;  
  5.     private Runnable mHeartBeatRunnable = new Runnable() {  
  6.   
  7.         @Override  
  8.         public void run() {  
  9.             if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {//每隔4秒检测一次  
  10.                 boolean isSuccess = sendHeartBeatMsg("");  
  11.                 if (!isSuccess) {  
  12.                     Log.i(TAG, "链接已断开,正在重连……");  
  13.                     mHandler.removeCallbacks(mHeartBeatRunnable);// 移除线程,重连时保证该线程已中止上次调用时的工做  
  14.                     mReadThread.release();//释放SocketReadThread线程资源  
  15.                     releaseLastSocket();  
  16.                     connectToServer();// 再次调用connectToServer方法,链接服务端  
  17.                 }  
  18.             }  
  19.             mHandler.postDelayed(this, HEART_BEAT_RATE);  
  20.         }  
  21.     };  
  22.     /** 
  23.      * 发送心跳包 
  24.      *  
  25.      * @param msg 
  26.      * @return 
  27.      */  
  28.     public boolean sendHeartBeatMsg(String msg) {  
  29.         if (null == mSocket) {  
  30.             return false;  
  31.         }  
  32.         try {  
  33.             if (!mSocket.isClosed() && !mSocket.isOutputShutdown()) {  
  34.                 String message = msg + "\r\n";  
  35.                 mDataOutputStream.write(message.getBytes());  
  36.                 mDataOutputStream.flush();  
  37.                 sendTime = System.currentTimeMillis();  
  38.             } else {  
  39.                 return false;  
  40.             }  
  41.         } catch (IOException e) {  
  42.             e.printStackTrace();  
  43.             return false;  
  44.         }  
  45.         return true;  
  46.     }  

        上述方法是心跳检测的主要方法,调用sendHeartBeatMsg()发送数据到服务端,该方法稍后给出。若是检测到链接断开,则释放各类资源,从新链接。若是链接没有断开则继续检测,很是简单的逻辑
this

  1. /** 
  2.   * 断开链接 
  3.   * 
  4.   */  
  5.     private void releaseLastSocket() {  
  6.         try {  
  7.             if (null != mSocket) {  
  8.                 if (!mSocket.isClosed()) {  
  9.                     mSocket.close();  
  10.                 }  
  11.             }  
  12.             mSocket = null;  
  13.         } catch (IOException e) {  
  14.             e.printStackTrace();  
  15.         }  
  16.     }  

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

  1. public class SocketReadThread extends Thread {  
  2.   
  3.         private static final String TAG = "SocketThread";  
  4.         private volatile boolean mStopThread = false;  
  5.         public void release() {  
  6.             mStopThread = true;  
  7.             releaseLastSocket();  
  8.         }  
  9.         @Override  
  10.         public void run() {  
  11.             DataInputStream mInputStream = null;  
  12.             try {  
  13.                 mInputStream = new DataInputStream(mSocket.getInputStream());  
  14.                 Logger.d(TAG, "SocketThread running!");  
  15.                 while (!mStopThread) {   
  16.                     String resultStr = mInputStream.readUTF();  
  17.                     handleStringMsg(resultStr);  
  18.                 }  
  19.             } catch (UnknownHostException e) {  
  20.                 e.printStackTrace();  
  21.             } catch (IOException e) {  
  22.                 e.printStackTrace();  
  23.             } finally {  
  24.                 try {  
  25.                     mSocket.close();  
  26.                 } catch (IOException e) {  
  27.                     e.printStackTrace();  
  28.                 }  
  29.                 if (mInputStream != null) {  
  30.                     try {  
  31.                         mInputStream.close();  
  32.                         mInputStream = null;  
  33.                     } catch (IOException e) {  
  34.                         e.printStackTrace();  
  35.                     }  
  36.                 }  
  37.             }  
  38.         }