• [置顶] android 心跳包的分析


                                                                          android 心跳的分析

           最近在做一个项目中用到了心跳包的机制,其实就是传统的长连接。或许有的人知道消息推送的机制,消息推送也是一种长连接 ,是将数据有服务器端推送到客户端这边从而改变传统的“拉”的请求方式。下面我来介绍一下安卓和客户端两个数据请求的方式

           1、push  这个也就是有服务器推送到客户端这边  现在有第三方技术 比如极光推送。

           2、pull   这种方式就是客户端向服务器发送请求数据(http请求)


       接下来 我就给大家介绍 Socket  tcp心跳包的机制   虽然这块不是很难,找一些网上的资料不是很全面   这个模块参照一个朋友的功能模块  自己也受益匪浅,现在分享给大家。

         一、首先服务器和客户端有一次“握手”

           public void connect()

          {
            LogUtil.e(TAG, "准备链接...");
            InetAddress serverAddr;
            try {
                socket = new Socket(Config.Host, Config.SockectPort);
                _connect = true;
                mReceiveThread = new ReceiveThread();
                receiveStop = false;
                mReceiveThread.start();
                LogUtil.e(TAG, "链接成功.");

            } catch (Exception e) {
                LogUtil.e(TAG, "链接出错." + e.getMessage().toString());
                e.printStackTrace();
            }
        }


       二、下面就要开启一个线程  去不断读取服务器那边传过来的数据  采用Thread去实现

         private class ReceiveThread extends Thread {
            private byte[] buf;
            private String str = null;

            @Override
            public void run() {
                while (true) {
                    try {
                        // LogUtil.e(TAG, "监听中...:"+socket.isConnected());
                        if (socket!=null && socket.isConnected()) {

                            if (!socket.isInputShutdown()) {
                                BufferedReader inStream = new BufferedReader(
                                        new InputStreamReader(
                                                socket.getInputStream()));
                                String content = inStream.readLine();                            
                                if (content == null)
                                    continue;
                                LogUtil.e(TAG, "收到信息:" + content);
                                LogUtil.e(TAG, "信息长度:"+content.length());
                                if (!content.startsWith("CMD:"))
                                    continue;
                                int spacePos = content.indexOf(" ");
                                if (spacePos == -1)
                                    continue;
                                String cmd = content.substring(4, spacePos);
    //                            String body = StringUtil.DecodeBase64(content
    //                                    .substring(spacePos));
                                String body = content.substring(spacePos).trim();
                                LogUtil.e(TAG, "收到信息(CMD):" + cmd);
                                LogUtil.e(TAG, "收到信息(BODY):" + body);

                                if (cmd.equals("LOGIN"))

                               {
                                    // 登录
                                    ReceiveLogin(body);
                                    continue;
                                }

                                  if (cmd.equals("KEEPLIVE")) {
                                    if (!body.equals("1")) {
                                        Log.e(TAG, "心跳时检测到异常,重新登录!");
                                        socket = null;
                                        KeepAlive();
                                    } else {
                                        Date now = Calendar.getInstance().getTime();
                                        lastKeepAliveOkTime = now;
                                    }
                                    continue;
                                }
                            }
                        } else {
                            if(socket!=null)
                                LogUtil.e(TAG, "链接状态:" + socket.isConnected());
                        }

                    } catch (Exception e) {
                        LogUtil.e(TAG, "监听出错:" + e.toString());
                        e.printStackTrace();
                    }
                }
            }

          三 、 Socket 是否断开了  断开了 需要重新去连接

             public void KeepAlive()

            {
            // 判断socket是否已断开,断开就重连
            if (lastKeepAliveOkTime != null) {
                LogUtil.e(
                        TAG,
                        "上次心跳成功时间:"
                                + DateTimeUtil.dateFormat(lastKeepAliveOkTime,
                                        "yyyy-MM-dd HH:mm:ss"));
                Date now = Calendar.getInstance().getTime();
                long between = (now.getTime() - lastKeepAliveOkTime.getTime());// 得到两者的毫秒数
                if (between > 60 * 1000) {
                    LogUtil.e(TAG, "心跳异常超过1分钟,重新连接:");
                    lastKeepAliveOkTime = null;
                    socket = null;
                }

            } else {
                lastKeepAliveOkTime = Calendar.getInstance().getTime();
            }

            if (!checkIsAlive()) {
                LogUtil.e(TAG, "链接已断开,重新连接.");
                connect();
                if (loginPara != null)
                    Login(loginPara);
            }


        //此方法是检测是否连接

          boolean checkIsAlive() {
            if (socket == null)
                return false;
            try {
                socket.sendUrgentData(0xFF);
            } catch (IOException e) {
                return false;
            }
            return true;

        }

       //然后发送数据的方法

        public void sendmessage(String msg) {
            if (!checkIsAlive())
                return;
            LogUtil.e(TAG, "准备发送消息:" + msg);
            try {
                if (socket != null && socket.isConnected()) {
                    if (!socket.isOutputShutdown()) {
                        PrintWriter outStream = new PrintWriter(new BufferedWriter(
                                new OutputStreamWriter(socket.getOutputStream())),
                                true);

                        outStream.print(msg + (char) 13 + (char) 10);
                        outStream.flush();
                    }
                }
                LogUtil.e(TAG, "发送成功!");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


        有什么问题欢迎大家一起讨论和学习  接下来自己准备研究手机流媒体这块  欢迎大家一起学习共同进步!

        源码下载地址:http://download.csdn.net/detail/wangliang198901/6567561

               

            

               

  • 相关阅读:
    一款非常推荐的用户界面插件----EasyUI
    使用chart和echarts制作图表
    JS模拟实现封装的三种方法
    JavaScript面向对象(OOP)
    移动HTML5前端框架—MUI
    一款优秀的前端JS框架—AngularJS
    less和scss
    JS中的正则表达式
    JS中的数组
    js匿名函数
  • 原文地址:https://www.cnblogs.com/riasky/p/3429275.html
Copyright © 2020-2023  润新知