抑郁症健康,内容丰富有趣,生活中的好帮手!
抑郁症健康 > Android Socket通信 发送心跳包 重连

Android Socket通信 发送心跳包 重连

时间:2019-08-08 16:35:03

相关推荐

最近项目中,有使用Socket与后端进行通信,然后简单的了解了下Socket使用,大致流程是配置服务端的Ip、端口号,连接,监听数据和发送数据,数据的读取和发送都是以流的形式实现的,然后自己将项目中的代码写了简单的管理类,测试下代码。下面是demo的两个界面,连接和发送接收界面

这里使用了一个Tcp调试助手,模拟服务端发送和接收数据,通讯模式选择TcpService ,本地端口随意定义一个,保持和demo填写的端口号一致,demo里面的ip是你主机的ip地址,cmd下ipconfig查看

代码

一、初始化

public TcpManager initSocket(final String ip, final String port) {this.ip=ip;this.port=port;/* 开启读写线程*/threadStatus =true;new ReadThread().start();if (socket == null && connectThread == null) {connectThread = new Thread(new Runnable() {@Overridepublic void run() {socket = new Socket();try {/*超时时间为2秒*/socket.connect(new InetSocketAddress(ip, Integer.valueOf(port)), 2000);/*连接成功的话 发送心跳包*/if (socket.isConnected()) {inputStream = socket.getInputStream();dis = new DataInputStream(inputStream);/*因为Toast是要运行在主线程的 这里是子线程 所以需要到主线程哪里去显示toast*/Log.e(TAG, "服务连接成功");/*发送连接成功的消息*/if(onSocketStatusListener!=null)onSocketStatusListener.onConnectSuccess();/*发送心跳数据*/sendBeatData();}} catch (IOException e) {e.printStackTrace();if (e instanceof SocketTimeoutException) {Log.e(TAG,"连接超时,正在重连");releaseSocket();} else if (e instanceof NoRouteToHostException) {Log.e(TAG,"该地址不存在,请检查");} else if (e instanceof ConnectException) {Log.e(TAG,"连接异常或被拒绝,请检查");}}}});/*启动连接线程*/connectThread.start();}return this;}

二、发送数据

public void sendData(final String data) {if (socket != null && socket.isConnected()) {/*发送指令*/new Thread(new Runnable() {@Overridepublic void run() {try {outputStream = socket.getOutputStream();if (outputStream != null) {outputStream.write((data).getBytes("UTF-8"));outputStream.flush();}} catch (IOException e) {e.printStackTrace();}}}).start();} else {Log.e(TAG,"socket连接错误,请重试");}}

三、读取数据

private class ReadThread extends Thread {@Overridepublic void run() {super.run();//判断进程是否在运行,更安全的结束进程while (threadStatus) {if (inputStream != null) {try {rcvLength = dis.read(buff);if (rcvLength > 0) {rcvMsg = new String(buff, 0, rcvLength, "GBK");//接收到数据,切换主线程,显示数据handler.post(new Runnable() {@Overridepublic void run() {if(onReceiveDataListener!=null){onReceiveDataListener.onReceiveData(rcvMsg);}}});}} catch (Exception e) {Log.e(TAG,"接收总控数据异常");}}}}}

四、全部代码

package com.yufs.testsocket.tcp;import android.os.Handler;import android.os.Looper;import android.util.Log;import java.io.DataInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import .ConnectException;import .InetSocketAddress;import .NoRouteToHostException;import .Socket;import .SocketTimeoutException;import java.util.Timer;import java.util.TimerTask;public class TcpManager {private static final String TAG = TcpManager.class.getSimpleName();/*socket*/private Socket socket;/*连接线程*/private Thread connectThread;/* 发送输出流*/private OutputStream outputStream;/* 读写输入流*/private InputStream inputStream;private DataInputStream dis;/* 线程状态,安全结束线程*/private boolean threadStatus =false;/* 读取保存进数组*/byte buff[] = new byte[1024*1024*2];private String ip;private String port;private Handler handler = new Handler(Looper.getMainLooper());/*默认重连*/private boolean isReConnect = true;/*倒计时Timer发送心跳包*/private Timer timer;private TimerTask task;/* 心跳周期(s)*/private int heartCycle = 30;/*接收数据长度*/private int rcvLength;/*接收数据*/private String rcvMsg;private TcpManager(){}private static TcpManager instance;public static synchronized TcpManager getInstance(){if(instance==null){synchronized (TcpManager.class){instance=new TcpManager();}}return instance;}public TcpManager initSocket(final String ip, final String port) {this.ip=ip;this.port=port;/* 开启读写线程*/threadStatus =true;new ReadThread().start();if (socket == null && connectThread == null) {connectThread = new Thread(new Runnable() {@Overridepublic void run() {socket = new Socket();try {/*超时时间为2秒*/socket.connect(new InetSocketAddress(ip, Integer.valueOf(port)), 2000);/*连接成功的话 发送心跳包*/if (socket.isConnected()) {inputStream = socket.getInputStream();dis = new DataInputStream(inputStream);/*因为Toast是要运行在主线程的 这里是子线程 所以需要到主线程哪里去显示toast*/Log.e(TAG, "服务连接成功");/*发送连接成功的消息*/if(onSocketStatusListener!=null)onSocketStatusListener.onConnectSuccess();/*发送心跳数据*/sendBeatData();}} catch (IOException e) {e.printStackTrace();if (e instanceof SocketTimeoutException) {Log.e(TAG,"连接超时,正在重连");releaseSocket();} else if (e instanceof NoRouteToHostException) {Log.e(TAG,"该地址不存在,请检查");} else if (e instanceof ConnectException) {Log.e(TAG,"连接异常或被拒绝,请检查");}}}});/*启动连接线程*/connectThread.start();}return this;}/*发送数据*/public void sendData(final String data) {if (socket != null && socket.isConnected()) {/*发送指令*/new Thread(new Runnable() {@Overridepublic void run() {try {outputStream = socket.getOutputStream();if (outputStream != null) {outputStream.write((data).getBytes("UTF-8"));outputStream.flush();}} catch (IOException e) {e.printStackTrace();}}}).start();} else {Log.e(TAG,"socket连接错误,请重试");}}/*定时发送数据*/private void sendBeatData() {if (timer == null) {timer = new Timer();}if (task == null) {task = new TimerTask() {@Overridepublic void run() {try {outputStream = socket.getOutputStream();Log.i(TAG,"发送心跳包");/*这里的编码方式根据你的需求去改*/outputStream.write(("test\n").getBytes("UTF-8"));outputStream.flush();} catch (Exception e) {/*发送失败说明socket断开了或者出现了其他错误*/Log.e(TAG,"连接断开,正在重连");/*重连*/releaseSocket();e.printStackTrace();}}};}timer.schedule(task, 0, 1000*heartCycle);}/*释放资源*/private void releaseSocket(){if (task != null) {task.cancel();task = null;}if (timer != null) {timer.purge();timer.cancel();timer = null;}if (outputStream != null) {try {outputStream.close();} catch (IOException e) {e.printStackTrace();}outputStream = null;}if(inputStream!=null){try {inputStream.close();} catch (IOException e) {e.printStackTrace();}inputStream=null;}if(dis!=null){try {dis.close();} catch (IOException e) {e.printStackTrace();}dis=null;}if (socket != null) {try {socket.close();} catch (IOException e) {}socket = null;}if (connectThread != null) {connectThread = null;}/*重新初始化socket*/if (isReConnect) {initSocket(ip,port);}}private class ReadThread extends Thread {@Overridepublic void run() {super.run();//判断进程是否在运行,更安全的结束进程while (threadStatus) {if (inputStream != null) {try {rcvLength = dis.read(buff);if (rcvLength > 0) {rcvMsg = new String(buff, 0, rcvLength, "GBK");//接收到数据,切换主线程,显示数据handler.post(new Runnable() {@Overridepublic void run() {if(onReceiveDataListener!=null){onReceiveDataListener.onReceiveData(rcvMsg);}}});}} catch (Exception e) {Log.e(TAG,"接收总控数据异常");}}}}}public interface OnSocketStatusListener{void onConnectSuccess();}public OnSocketStatusListener onSocketStatusListener;public void setOnSocketStatusListener(OnSocketStatusListener onSocketStatusListener) {this.onSocketStatusListener = onSocketStatusListener;}public interface OnReceiveDataListener{void onReceiveData(String str);}public OnReceiveDataListener onReceiveDataListener;public void setOnReceiveDataListener(OnReceiveDataListener onReceiveDataListener) {this.onReceiveDataListener = onReceiveDataListener;}}

总体来说分为三步:连接、发送、线程监听数据,这里连接状态和接收数据使用了监听事件,可以考虑使用EventBus。整个代码写在一个工具类里面,里面还有很多需要优化的地方。不如说将这些写在服务里面,服务的生命周期与界面绑定。还有数据的读取这一方面好像有长度限制,超过一定长度,它就分为两次或三次,这个问题待解决,不过应对小数据的通信是没有问题的。

demo下载

如果觉得《Android Socket通信 发送心跳包 重连》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。