美文网首页涛锅锅的Android资料
在Android上面如何使用带有心跳检测的Socket

在Android上面如何使用带有心跳检测的Socket

作者: 我是涛锅锅 | 来源:发表于2017-09-08 10:32 被阅读37次

    由于移动设备的网络的复杂性,经常会出现网络断开,如果没有心跳包的检测,客户端只会在需要发送数据的时候才知道自己已经断线,会延误,甚至丢失服务器发送过来的数据。一下简单建立一个带有心跳检测的SocketDemo。

    Android 后台Servevice

    package org.feng.sockettest.server;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    import java.lang.ref.WeakReference;
    import java.net.Socket;import java.net.UnknownHostException;
    import java.util.Arrays;
    import android.app.Service;
    import android.content.Intent;
    import android.os.Handler;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v4.content.LocalBroadcastManager;
    import android.util.Log;
    
    public class BackService extends Service { 
        private static final String TAG = "BackService"; 
        private static final long HEART_BEAT_RATE = 3 * 1000; 
        public static final String HOST = "192.168.1.101";// "192.168.1.21";// 
        public static final int PORT = 9800; 
        public static final String MESSAGE_ACTION="org.feng.message_ACTION"; 
        public static final String HEART_BEAT_ACTION="org.feng.heart_beat_ACTION"; 
        private ReadThread mReadThread; 
        private LocalBroadcastManager mLocalBroadcastManager;   
        private WeakReference<Socket> mSocket; // For heart Beat     
        private Handler mHandler = new Handler();
        private Runnable heartBeatRunnable = new Runnable() { 
            @Override 
            public void run() {
                if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) { 
                    boolean isSuccess = sendMsg("");//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket 
                    if (!isSuccess) {                   
                    mHandler.removeCallbacks(heartBeatRunnable);                    
                    mReadThread.release();                  
                    releaseLastSocket(mSocket); 
                    new InitSocketThread().start();             
                    }           
                }           
            mHandler.postDelayed(this, HEART_BEAT_RATE);
            }   
        }; 
        private long sendTime = 0L; 
        private IBackService.Stub iBackService = new IBackService.Stub() { 
            @Override 
            public boolean sendMessage(String message) throws RemoteException { 
                return sendMsg(message);        
            }   
        }; 
    
        @Override 
        public IBinder onBind(Intent arg0) { 
            return iBackService;    
        } 
    
        @Override 
        public void onCreate() { 
            super.onCreate(); 
            new InitSocketThread().start();     
            mLocalBroadcastManager=LocalBroadcastManager.getInstance(this);         
        } 
        public boolean sendMsg(String msg) { 
            if (null == mSocket || null == mSocket.get()) { 
                return false;       
            }       
            Socket soc = mSocket.get();
            try { 
                if (!soc.isClosed() && !soc.isOutputShutdown()) {
                    OutputStream os = soc.getOutputStream();                
                    String message = msg + "\r\n";                                  
                    os.write(message.getBytes());               
                    os.flush();             
                    sendTime = System.currentTimeMillis();//每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间 
                } else { 
                    return false;           
                }       
            } catch (IOException e) {           
                e.printStackTrace(); 
                return false;       
            }
            return true;    
        } 
        private void initSocket() {
        //初始化Socket 
            try {           
                Socket so = new Socket(HOST, PORT);         
                mSocket = new WeakReference<Socket>(so);    
                mReadThread = new ReadThread(so);           
                mReadThread.start();            
                mHandler.postDelayed(heartBeatRunnable,             
                HEART_BEAT_RATE);//初始化成功后,就准备发送心跳包 
            } catch (UnknownHostException e) {
                e.printStackTrace();        
            } catch (IOException e) {           
                e.printStackTrace();        
            }   
        } 
        private void releaseLastSocket(WeakReference<Socket> mSocket){ 
            try { 
                if (null != mSocket) {              
                    Socket sk = mSocket.get(); 
                    if (!sk.isClosed()) {                   
                        sk.close();             
                    }               
                    sk = null;              
                    mSocket = null;         
                }       
            } catch (IOException e) {           
                e.printStackTrace();        
            }   
        } 
        class InitSocketThread extends Thread { 
            @Override 
            public void run() { 
                super.run();            
                initSocket();       
            }   
        } 
        // Thread to read content from Socket 
        class ReadThread extends Thread { 
            private WeakReference<Socket> mWeakSocket; 
            private boolean isStart = true; 
            public ReadThread(Socket socket) {          
                mWeakSocket = new WeakReference<Socket>(socket);        
            } 
            public void release() {         
                isStart = false;            
                releaseLastSocket(mWeakSocket);     
            } 
            @Override 
            public void run() { 
                super.run();            
                Socket socket = mWeakSocket.get();
                 if (null != socket) { 
                    try {                   
                        InputStream is = socket.getInputStream(); 
                        byte[] buffer = new byte[1024 * 4];
                        int length = 0; 
                        while (!socket.isClosed() &&!socket.isInputShutdown()&& isStart && ((length = is.read(buffer)) != -1)) {
                            if (length > 0) {                           
                                String message = new String(Arrays.copyOf(buffer,length)).trim();                           
                                Log.e(TAG, message); //收到服务器过来的消息,就通过Broadcast发送出去 
                                if(message.equals("ok")){
                                    //处理心跳回复 
                                    Intent intent=new Intent(HEART_BEAT_ACTION);                                
                                    mLocalBroadcastManager.sendBroadcast(intent);                           
                                }else{ 
                                    //其他消息回复 
                                    Intent intent=new Intent(MESSAGE_ACTION);                               
                                    intent.putExtra("message", message);                                
                                    mLocalBroadcastManager.sendBroadcast(intent);                           
                                }                       
                            }                   
                        }               
                    } catch (IOException e) {                   
                        e.printStackTrace();                
                    }           
                }       
            }   
        }
    }
    

    在Activity中发送以及接收数据:

    package org.feng.sockettest;
    import java.lang.ref.WeakReference;
    import org.feng.sockettest.server.BackService;
    import org.feng.sockettest.server.IBackService;
    import android.app.Activity;
    import android.content.BroadcastReceiver;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.IntentFilter;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.support.v4.content.LocalBroadcastManager;
    import android.view.View;
    import android.widget.EditText;
    import android.widget.TextView;
    import android.widget.Toast;
    
    
    public class MainActivity extends Activity { 
        private static final String TAG = "MainActivity"; 
        private IBackService iBackService; 
        private ServiceConnection conn = new ServiceConnection() { 
            @Override 
            public void onServiceDisconnected(ComponentName name) {         
                iBackService = null;        
            } 
            @Override 
            public void onServiceConnected(ComponentName name, IBinder service) {           
                iBackService = IBackService.Stub.asInterface(service);      
            }   
        }; 
        private TextView mResultText; 
        private EditText mEditText; 
        private Intent mServiceIntent; 
        class MessageBackReciver extends BroadcastReceiver { 
            private WeakReference<TextView> textView; 
            public MessageBackReciver(TextView tv) {            
                textView = new WeakReference<TextView>(tv);     
            } 
            @Override 
            public void onReceive(Context context, Intent intent) {         
                String action = intent.getAction();         
                TextView tv = textView.get();
                 if (action.equals(BackService.HEART_BEAT_ACTION)) { 
                    if (null != tv) {                   
                        tv.setText("Get a heart heat");             
                    }           
                } else {                
                    String message = intent.getStringExtra("message");              
                    tv.setText(message);            
                }       
            };  
        } 
        private MessageBackReciver mReciver; 
        private IntentFilter mIntentFilter; 
        private LocalBroadcastManager mLocalBroadcastManager; 
        @Override 
        public void onCreate(Bundle savedInstanceState) { 
            super.onCreate(savedInstanceState);     
            setContentView(R.layout.activity_main);     
            mLocalBroadcastManager = LocalBroadcastManager.getInstance(this);       
            mResultText = (TextView) findViewById(R.id.resule_text);        
            mEditText = (EditText) findViewById(R.id.content_edit);     
            mReciver = new MessageBackReciver(mResultText);     
            mServiceIntent = new Intent(this, BackService.class);       
            mIntentFilter = new IntentFilter();     
            mIntentFilter.addAction(BackService.HEART_BEAT_ACTION);     
            mIntentFilter.addAction(BackService.MESSAGE_ACTION);    
        } 
        @Override 
        protected void onStart() { 
            super.onStart();        
            mLocalBroadcastManager.registerReceiver(mReciver, mIntentFilter);       
            bindService(mServiceIntent, conn, BIND_AUTO_CREATE);    
        } 
        @Override 
        protected void onStop() { 
            super.onStop();     
            unbindService(conn);        
            mLocalBroadcastManager.unregisterReceiver(mReciver);    
        } 
        public void onClick(View view) { 
            switch (view.getId()) { 
                case R.id.send:         
                    String content = mEditText.getText().toString(); 
                    try { 
                        boolean isSend = iBackService.sendMessage(content);//Send Content by socket 
                        Toast.makeText(this, isSend ? "success" : "fail",                       Toast.LENGTH_SHORT).show();             
                        mEditText.setText("");          
                    } catch (RemoteException e) {               
                        e.printStackTrace();            
                    } 
                    break; 
                default: break;     
            }   
        }
    }
    

    完整项目带服务器段代码的见http://git.oschina.net/fengcunhan/SocketTest.git
    该文章转载自:https://my.oschina.net/fengcunhan/blog/178155

    相关文章

      网友评论

        本文标题:在Android上面如何使用带有心跳检测的Socket

        本文链接:https://www.haomeiwen.com/subject/qmkgjxtx.html