您的位置:首页 > 移动开发 > Android开发

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

2015-08-12 00:45 399 查看
由于移动设备的网络的复杂性,经常会出现网络断开,如果没有心跳包的检测,客户端只会在需要发送数据的时候才知道自己已经断线,会延误,甚至丢失服务器发送过来的数据。一下简单建立一个带有心跳检测的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(Bu
4000
ndle 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android