android TCP长连接+心跳包

释放双眼,带上耳机,听听看~!
import android.os.Bundle;
import android.text.TextUtils;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import com.ysl.socket.broad.SockeBroadcastReceiver;
import com.ysl.socket.interfaces.SocketCallback;
import android.app.Activity;
import android.content.IntentFilter;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
public static String str = "first message...";
private SockeBroadcastReceiver mHeartBeatBroadCast;
private TextView txtMsg;
private Button send;
private EditText etMsg;
private String content;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_socket);
socketTest();
}
@Override
protected void onResume()
{
super.onResume();
IntentFilter mIntentFilter = new IntentFilter();
mIntentFilter.addAction(SockeBroadcastReceiver.HEART_BEAT_ACTION);
mIntentFilter.addAction(SockeBroadcastReceiver.MESSAGE_ACTION);
registerReceiver(mHeartBeatBroadCast, mIntentFilter);
}
@Override
protected void onDestroy()
{
super.onDestroy();
unregisterReceiver(mHeartBeatBroadCast);
}
//***socke测试 start*****************
private void socketTest(){
txtMsg = (TextView) findViewById(R.id.txt1);
txtMsg.setMovementMethod(ScrollingMovementMethod.getInstance());  //滚动条
send = (Button) findViewById(R.id.send);
etMsg = (EditText) findViewById(R.id.ed1);
send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
content = etMsg.getText().toString();
content = "FE0099CF010A01005243FE";
if (TextUtils.isEmpty(content)){
Toast.makeText(MainActivity.this, "消息不能为空", Toast.LENGTH_SHORT).show();
return;
}
boolean sendState = mHeartBeatBroadCast.sendMsg(content);
if (sendState){
Toast.makeText(MainActivity.this, "SendSuccess", Toast.LENGTH_SHORT).show();
setMessages("客户端发送消息:"+content);
//                 etMsg.setText("");
}else{
Toast.makeText(MainActivity.this, "SendFail", Toast.LENGTH_SHORT).show();
}
}
});
mHeartBeatBroadCast = new SockeBroadcastReceiver(this);
setMessages("正在连接到服务器(" + mHeartBeatBroadCast.HOST + ":" + mHeartBeatBroadCast.PORT  +  ")...");
mHeartBeatBroadCast.setSocketCallback(new SocketCallback()
{
@Override
public void connected()
{
Log.i("ysl", "服务器连接了...");
runOnUiThread(new Runnable()
{
@Override
public void run()
{
setMessages("已连接到服务器...");
}
});
}
@Override
public void disConnected(){
Log.i("ysl", "服务器断开了...");
runOnUiThread(new Runnable()
{
@Override
public void run()
{
setMessages("服务器断开,自动重连中...");
}
});
mHeartBeatBroadCast.initSocket();
}
@Override
public void receiveMessage(String message)
{
Log.i("ysl", "收到新消息:" + message);
setMessages("JAVA服务端: " + message);
}
});
}
/**
* 设置TextView文本
* @param message
*/
public void setMessages(String message){
txtMsg.append(message + "n");
//    txtMsg.setText(txtMsg.getText().toString() + "n" + message);
int offset = txtMsg.getLineCount() * txtMsg.getLineHeight();
if(offset > txtMsg.getHeight()){
txtMsg.scrollTo(0,offset-txtMsg.getHeight());
}
}
}
/**
* 模拟服务器  可直接运行
*/
public class AndroidService
{
public static void main(String[] args) throws IOException
{
ServerSocket serivce = new ServerSocket(6000);
//    System.out.println("服务器已运行...");
System.out.print("服务器已经运行======");
while (true) {
//等待客户端连接
Socket socket = serivce.accept();
new Thread(new AndroidRunable(socket)).start();
}
}
}
**
* 测试socket用的线程
*/
public class AndroidRunable implements Runnable
{
Socket socket = null;
String str = "ok";
public AndroidRunable(Socket socket)
{
this.socket = socket;
}
@Override
public void run()
{
// 向android客户端输出hello worild
String line = null;
InputStream input;
OutputStream output;
try
{
// 向客户端发送信息
output = socket.getOutputStream();
input = socket.getInputStream();
byte[] buffer = new byte[1024 * 4];
int length = 0;
//       output.write(str.getBytes("UTF-8"));
//       output.flush();
// 半关闭socket
//       socket.shutdownOutput();
//获取客户端发来的信息
while (!socket.isClosed() && ((length = input.read(buffer)) != -1))
{
String message = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.GINGERBREAD) {
message = new String(Arrays.copyOf(buffer, length)).trim();
}
System.out.print("服务器接收到的消息:n" + message + "n");
if ("xt".equals(message))  //收到心跳
{
output.write("收到心跳".getBytes("UTF-8"));
output.flush();
}
}
// 关闭输入输出流
output.close();
input.close();
socket.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
/**
* input-->string
* @param in
* @return
* @throws IOException
*/
public static String inputStream2String(InputStream in) throws IOException
{
StringBuffer out = new StringBuffer();
byte[] b = new byte[4096];
int n;
while ((n = in.read(b)) != -1)
{
out.append(new String(b, 0, n));
}
return out.toString();
}
}
/**
* Socket长链接核心类
* 1.定时与服务器心跳保持(时间可以自定义)
* 2.断线自动重连
* 3.连接成功、断开连接、收到消息回调处理
* 4.消息发送状态获取(成功true or 失败false)
* 5.注册广播
*/
public class SockeBroadcastReceiver extends BroadcastReceiver
{
private static final String TAG = "ysl";
/** 心跳检测时间 */
private static final long HEART_BEAT_RATE = 3 * 1000;
/** 主机IP地址 */
public static final String HOST = "192.168.0.1";
// public static final String HOST = "101.200.191.35";
/** 端口号 */
public static final int PORT = 6000;
/** 超时设置 **/
public static final int SOCKET_TIME_OUT = 10 * 1000;
/** 消息广播 */
public static final String MESSAGE_ACTION = "com.ysl.message_ACTION";
/** 心跳广播 */
public static final String HEART_BEAT_ACTION = "com.ysl.heart_beat_ACTION";
/** 线程池 **/
private ExecutorService executorService = Executors.newFixedThreadPool(5);
/** 为了节省开销:如果最后发送时间间隔不超过心跳时间则不发心跳 */
private long sendTime = 0L;
private ReadThread mReadThread;
private MainActivity mMainActivity;
private Socket socket;
private boolean isConnected = true; //是否处于连接状态
private SocketCallback callback; // 回调
/**
* 初始化
* @param mMainActivity
*/
public SockeBroadcastReceiver(MainActivity mMainActivity)
{
this.mMainActivity = mMainActivity;
initSocket();
}
/**
* 设置状态回调
* @param callback
*/
public void setSocketCallback(SocketCallback callback){
this.callback = callback;
}
/**
* 初始化Socake
*/
public void initSocket()
{
executorService.execute(new Runnable()
{
@Override
public void run()
{
try
{
socket = new Socket();
SocketAddress socAddress = new InetSocketAddress(HOST,PORT);
socket.connect(socAddress, SOCKET_TIME_OUT);
if (callback != null)  //链接成功
{
isConnected = true;
callback.connected();
}
mReadThread = new ReadThread();
mReadThread.start();
mHandler.postDelayed(heartBeatRunnable, HEART_BEAT_RATE);// 初始化成功后,就准备发送心跳包
} catch (UnknownHostException e)
{
if (callback != null)  //链接失败
{
isConnected = false;
callback.disConnected();
}
e.printStackTrace();
} catch (IOException e)
{
if (callback != null)  //链接失败
{
isConnected = false;
callback.disConnected();
}
e.printStackTrace();
}
}
});
}
@Override
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (action.equals(MESSAGE_ACTION)){ // 消息广播
String stringExtra = intent.getStringExtra("message");
//       Log.i(TAG, "收到服务器消息:" + stringExtra);
if (callback != null)
{
callback.receiveMessage(stringExtra);
}
} else if (action.equals(HEART_BEAT_ACTION)){// 心跳广播
Log.i("ysl", "收到服务器正常心跳。");
}
}
/**
* 发送心跳包
*/
private Handler mHandler = new Handler();
private Runnable heartBeatRunnable=new Runnable(){
@Override
public void run(){
if(System.currentTimeMillis()-sendTime>=HEART_BEAT_RATE){
//          boolean isSuccess=sendMsg("xt");// 可以随意与服务器定义好内容。。。
boolean isSuccess=sendMsg("FE0099CF010B0114000031303038303030313135343630353238303296A1FE");// 可以随意与服务器定义好内容。。。
if(!isSuccess){ // 如果发送不成功重连
mHandler.removeCallbacks(heartBeatRunnable);
mReadThread.release();
releaseLastSocket(socket);
if (callback != null)
{
callback.disConnected();
}
}
}
mHandler.postDelayed(this,HEART_BEAT_RATE);
}
};
/**
* 发送消息
* @param msg
* @return
*/
public boolean sendMsg(String msg)
{
if (null == socket){
return false;
}
try
{
if (!socket.isClosed() && !socket.isOutputShutdown() && isConnected)
{
OutputStream os = socket.getOutputStream();
String message = msg;
//          +"rn";
//          os.write(message.getBytes());
os.write(toBytes(msg));
os.flush();
sendTime = System.currentTimeMillis();// 每次发送成功数据,就改一下最后成功发送的时间,节省心跳间隔时间
Log.i(TAG, "发送成功的时间:" + sendTime);
} else
{
return false;
}
} catch (IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
/**
* 将16进制字符串转换为byte[]
*  FE0099CF010A01005243FE
* @param str
* @return
*/
public static byte[] toBytes(String str) {
if(str == null || str.trim().equals("")) {
return new byte[0];
}
byte[] bytes = new byte[str.length() / 2];
for(int i = 0; i < str.length() / 2; i++) {
String subStr = str.substring(i * 2, i * 2 + 2);
bytes[i] = (byte) Integer.parseInt(subStr, 16);
}
//        Log.e("tag1",BytesHexStrTranslate.bytesToHexFun1(bytes)+"");
//        Log.e("tag1111111", bytes + "");
return bytes;
}
/**
* 释放socket
* @param mSocket
*/
private void releaseLastSocket(Socket mSocket)
{
try
{
if (null != mSocket)
{
if (!mSocket.isClosed())
{
mSocket.close();
}
mSocket = null;
}
} catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 接收消息
*/
public class ReadThread extends Thread
{
private boolean isStart = true;
public void release()
{
isStart = false;
releaseLastSocket(socket);
}
@SuppressLint("NewApi")
@Override
public void run()
{
if (null != socket && isConnected)
{
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))
{
isConnected = true;
if (length > 0)
{
String message = new String(Arrays.copyOf(buffer, length)).trim();
// 收到服务器过来的消息,就通过Broadcast发送出去
if (message.equals("ok"))
{// 处理心跳回复
Intent intent = new Intent(HEART_BEAT_ACTION);
mMainActivity.sendBroadcast(intent);
} else
{ // 其他消息回复
Intent intent = new Intent(MESSAGE_ACTION);
intent.putExtra("message", message);
mMainActivity.sendBroadcast(intent);
}
}
}
isConnected = false;
if (callback != null)
{
callback.disConnected();
}
} catch (IOException e)
{
isConnected = false;
if (callback != null)
{
callback.disConnected();
}
e.printStackTrace();
Log.i("ysl", "已经断开IOException...");
}
}
}
}
}
public interface SocketCallback
{
void connected();
void disConnected();
void receiveMessage(String message);
}

人已赞赏
Android文章

Android实现图片滚动控件,含页签功能,让你的应用像淘宝一样炫起来

2020-3-19 23:43:06

Android文章

Android WebView中Http和Https混合问题,无法显示图片解决

2020-3-23 21:46:28

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
有新消息 消息中心
搜索