public class SocketService extends Service { private static final String TAG = "SocketService"; private static final long HEART_BEAT_RATE = 60 * 1000; private static final long RECONNECT_RATE = 3000; //3秒 重连 private ReadThread mReadThread; private WeakReference<Socket> mSocket; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { switch ( msg.what){ case Constants.ERR_CODE_FAIL: ToastUtil.showCenterToast(getApplicationContext(),"控制失败!"); break; case Constants.ERR_CODE_OFFLINE: ToastUtil.showCenterToast(getApplicationContext(),"设备离线!"); break; case Constants.ERR_CODE_TIMEOUT: ToastUtil.showCenterToast(getApplicationContext(),"超时!"); break; case Constants.ERR_CODE_CNT: break; default: break; } } }; /** * 心跳检测步骤: 1.客户端每隔一个时间间隔发生一个探测包给服务器 2.客户端发包时启动一个超时定时器 3.服务器端接收到检测包,应该回应一个包 4.如果客户机收到服务器的应答包,则说明服务器正常,删除超时定时器 5.如果客户端的超时定时器超时,依然没有收到应答包,则说明服务器挂了 */ private Runnable heartBeatRunnable = new Runnable() { @Override public void run() { if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) { boolean isSuccess = sendHeartBeat();//就发送一个\r\n过去 如果发送失败,就重新初始化一个socket if (!isSuccess) { mHandler.removeCallbacks(heartBeatRunnable); if(null!=mReadThread){ mReadThread.release(); } releaseLastSocket(mSocket); new InitSocketThread().start(); } } mHandler.postDelayed(this, HEART_BEAT_RATE); } }; /** * 断开重连 */ private Runnable reConnectRunnable = new Runnable() { @Override public void run() { mHandler.removeCallbacks(reConnectRunnable); if(null!=mReadThread){ mReadThread.release(); } releaseLastSocket(mSocket); new InitSocketThread().start(); } }; private boolean sendHeartBeat() { BaseRequestBean<String> bean=new BaseRequestBean<String>(); //设置访问参数 String json = GsonUtil.getGson().toJson(bean); return sendMsg(json); } private long sendTime = 0L; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onCreate() { super.onCreate(); EventBus.getDefault().register(this); new InitSocketThread().start(); } 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"; byte[] bytes = addTLV(os, msg.getBytes()); os.write(bytes); os.flush(); sendTime = System.currentTimeMillis();//每次发送成数据,就改一下最后成功发送的时间,节省心跳间隔时间 } else { dealDisconnected(); return false; } } catch (IOException e) { //错误,通道中断 ,没必要在发心跳包了 mHandler.removeCallbacks(heartBeatRunnable); dealSocketConnectException(e,0); return false; } return true; } private void initSocket() {//初始化Socket try { Log.i(TAG, "---------------------initSocket--------------"); Socket so = new Socket(Config.Host, Config.Post); mSocket = new WeakReference<Socket>(so); mReadThread = new ReadThread(so); mReadThread.start(); //连接成功,不断发送心跳包 mHandler.postDelayed(heartBeatRunnable, 0); //连接成功,移除重连任务 mHandler.removeCallbacks(reConnectRunnable); } catch (UnknownHostException e) { dealSocketConnectException(e,RECONNECT_RATE); } catch (IOException e) { dealSocketConnectException(e,RECONNECT_RATE); } } private void releaseLastSocket(WeakReference<Socket> mSocket) { try { if (null != mSocket) { Socket sk = mSocket.get(); if (null!=sk && !sk.isClosed()) { sk.close(); Log.e(TAG, "-------------------Socket 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*3]; int length = 0; byte [] data=null; boolean isContinue=false; int count=0; int lengthData=0; loop: while (!socket.isClosed() && !socket.isInputShutdown() && isStart && ((length = is.read(buffer)) != -1)) { String message=null; int tag = bytes2Int(buffer, 0); //from包含 ,to 不包含 //to 由length计算 数据长度+tag // new String(buffer,8,lengthData).trim(); //TLV数据,内容过长,则缓存起来,多次读取直到指定长度 if(tag==Constants.SOCKET_PROTO_TLV_TAG){ lengthData = bytes2Int(buffer, 4); if(lengthData+8>length){ if(null==data || data.length<lengthData){ data=new byte[lengthData]; } System.arraycopy(buffer ,8,data,0,length-8); isContinue=true; count=length-8; continue ; }else{ isContinue=false; count=0; message= new String(buffer,8,lengthData).trim(); } }else if(isContinue){ if(count+length<lengthData){ System.arraycopy(buffer ,0,data,count,length); isContinue=true; count=count+length; continue ; }else { System.arraycopy(buffer ,0,data,count,lengthData-count); message= new String(data,0,lengthData).trim(); isContinue=false; count=0; } } sendTime = System.currentTimeMillis();//每次接收到数据,就改一下最后成功发送的时间,节省心跳间隔时间 if(null!=message){ Log.e(TAG, message); dealResponseData(message); } } length = is.read(buffer); dealDisconnected(); } catch (IOException e) { dealSocketConnectException(e,0); } } } } //接收在其他页面发送的请求命令 @Subscribe public void onEventMainThread(AnyEventType eventType) { switch (eventType.getCmd()) { case Constants.EVENT_SEND: String json = GsonUtil.getGson().toJson(eventType.getObj()); sendMsg(json); break; default: break; } } @Override public boolean onUnbind(Intent intent) { EventBus.getDefault().unregister(this); Log.i(TAG, "---------------------onUnbind--------------"); return super.onUnbind(intent); } @Override public void onDestroy() { super.onDestroy(); Log.i(TAG, "---------------------onDestroy--------------"); mHandler.removeCallbacks(heartBeatRunnable); mHandler.removeCallbacks(reConnectRunnable); if(null!=mReadThread){ mReadThread.release(); } releaseLastSocket(mSocket); EventBus.getDefault().unregister(this); } private void dealSocketConnectException(Exception e,long delayMillis) { mHandler.postDelayed(reConnectRunnable, delayMillis); Log.e(TAG, "----------------------------"+e.getMessage()); } /** * 处理socket中断问题 */ private void dealDisconnected() { //服务端中断,重连, 第一次马上重连,第二次则按间隔时间 mHandler.postDelayed(reConnectRunnable, 0); //错误,通道中断 ,没必要在发心跳包了 mHandler.removeCallbacks(heartBeatRunnable); } public int bytes2Int(byte[] bytes,int pos){ int num=bytes[pos] & 0xFF; num |=((bytes[pos+1] <<8)& 0xFF00); num |=((bytes[pos+2] <<16)& 0xFF0000); num |=((bytes[pos+3] <<24)& 0xFF000000); return num; } public byte[] int2ByteArray(int i){ byte[] result=new byte[4]; //大小端 /* result[0]=(byte)((i >> 24)& 0xFF); result[1]=(byte)((i >> 16)& 0xFF); result[2]=(byte)((i >> 8)& 0xFF); result[3]=(byte)(i & 0xFF);*/ result[3]=(byte)((i >> 24)& 0xFF); result[2]=(byte)((i >> 16)& 0xFF); result[1]=(byte)((i >> 8)& 0xFF); result[0]=(byte)(i & 0xFF); return result; } /** * 对要发送的数据添加TLV * 变长头 * @param os * @param message * @return * @throws IOException */ private byte[] addTLV(OutputStream os, byte[] message) throws IOException { int pos=0; byte[] bytesTag = int2ByteArray(Constants.SOCKET_PROTO_TLV_TAG); byte[] bytesLength = int2ByteArray(message.length); int length=bytesLength.length+bytesTag.length+message.length; byte [] value = new byte[length]; //将tag标识复制到目标数组 System.arraycopy(bytesTag,0,value,0,bytesTag.length); pos=bytesTag.length; //将数据长度复制到目标数组 System.arraycopy(bytesLength,0,value,pos,bytesLength.length); pos=pos+bytesLength.length; //将要发送的内容复制到数组 System.arraycopy(message,0,value,pos,message.length); return value; } /** * 处理响应数据 * @param message */ private void dealResponseData(String message) { try { Type type = new TypeToken<BaseResponseBean>() {}.getType(); BaseResponseBean bean = (BaseResponseBean) GsonUtil.getGson().fromJson(message, type); if(null!=bean && bean.getStatus()==Constants.ERR_CODE_OK){ //收到服务器过来的消息,就通过Broadcast发送出去 if(bean.getCmd()==Constants.CMD_HEARTBEAT){//处理心跳回复 }else{ //其他消息回复 /*int type = jsonObject.getInt("type"); int seq = jsonObject.getInt("seq"); if(cmd==Constants.CMD_CTRL_SCENE){ Log.e("tag", message); }*/ JSONObject jsonObject = new JSONObject(message); String string=null; boolean isBodyNull = jsonObject.isNull("body"); if(!isBodyNull){ string = jsonObject.getString("body"); } //将响应结果发送出去 // EventBus.getDefault().post(); } }else if(null!=bean){ Log.e(TAG, bean.toString()); mHandler.sendEmptyMessage(bean.getStatus()); } } catch (JSONException e) { e.printStackTrace(); } } }
07-20
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交