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

           

        

           

  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是一个使用新线程循环发送心跳包的示例代码: ```java public class HeartbeatThread extends Thread { private final String TAG = "HeartbeatThread"; private final int HEARTBEAT_INTERVAL = 5000; // 心跳包发送间隔,单位为毫秒 private boolean isRunning = false; // 标志位,用于控制线程运行状态 @Override public void run() { isRunning = true; while (isRunning) { try { // 发送心跳包 // ... Thread.sleep(HEARTBEAT_INTERVAL); // 线程休眠,等待下一次发送心跳包 } catch (InterruptedException e) { Log.e(TAG, "HeartbeatThread interrupted!"); e.printStackTrace(); } } } public void stopThread() { isRunning = false; } } ``` 在使用该线程时需要注意,在发送心跳包的同时,需要在主线程中处理接收到的心跳回包,以保证心跳功能的正常运行。可以使用Handler或者BroadcastReceiver来实现。 另外,需要注意线程的停止问题。在Activity或者Service销毁时,应该调用stopThread()方法来停止心跳线程,避免出现内存泄漏的情况。 ```java public class MainActivity extends AppCompatActivity { private HeartbeatThread mHeartbeatThread; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHeartbeatThread = new HeartbeatThread(); mHeartbeatThread.start(); } @Override protected void onDestroy() { super.onDestroy(); if (mHeartbeatThread != null) { mHeartbeatThread.stopThread(); mHeartbeatThread = null; } } } ``` 需要注意的是,该示例代码仅供参考,具体实现还需要根据具体的业务需求来进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值