[置顶] 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
[置顶] android 心跳包的分析的更多相关文章
- [置顶] Android开发之serviceManager分析
		Android 开发之serviceManager分析 在Android系统中用到最多的通信机制就是Binder,Binder主要由Client.Server.ServiceManager和Binde ... 
- [置顶] Android开发笔记(成长轨迹)
		分类: 开发学习笔记2013-06-21 09:44 26043人阅读 评论(5) 收藏 Android开发笔记 1.控制台输出:called unimplemented OpenGL ES API ... 
- [置顶]
        Android逆向从未如此简单
		哈,又标题党了..不过我一定竭尽所能,写一篇最亲民的入门文章. 本文仅供学习交流之用,切勿用于非法用途,读者若运用所学知识,进行非法任何商业目的或者非法牟利,一切责任由操作者自行承担,与本人无关.希望 ... 
- [置顶] [Android源码分析]inquiry result引起的上层变化分析
		在上一篇文章中,我们详细分析了android是如何解析蓝牙反馈上来的搜索到的设备信息,本文将会继续分析这些信息到了上层之后是如何处理. 8.inquiry result引起的上层变化 我们知道inqu ... 
- [置顶] Android开发之ProcessState和IPCThreadState类分析
		在Android中ProcessState是客户端和服务端公共的部分,作为Binder通信的基础,ProcessState是一个singleton类,每个 进程只有一个对象,这个对象负责打开Binde ... 
- [置顶] Android安全机制分析
		Android系统是基于Linux内核开发的,因此,Android系统不仅保留和继承了Linux操作系统的安全机制,而且其系统架构的各个层次都有独特的安全特性[2] . 1. Linux内核层安全机制 ... 
- [置顶] Android资源文件分析
		1)修改开机默认壁纸 Android开机默认资源文件为:frameworks/base/core/res/res/values/config.xml 我们找到wallpaper行: <strin ... 
- [置顶] Android源码分析-点击事件派发机制
		转载请注明出处:http://blog.csdn.net/singwhatiwanna/article/details/17339857 概述 一直想写篇关于Android事件派发机制的文章,却一直没 ... 
- [置顶] Android开发之Thread类分析
		在我们Linux系统中创建线程函数为:pthread_create(),在Android中我们为线程封装了一个类Thread,实际调用的还是pthread_create() 当我们想创建线程的时候,只 ... 
随机推荐
- HDU 5787 K-wolf Number(数位DP)
			[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5787 [题目大意] 求区间[L,R]内十进制数相邻k位之间不相同的数字的个数. [题解] 很显然的 ... 
- Codeforces 700A As Fast As Possible(二分答案)
			[题目链接] http://codeforces.com/problemset/problem/700/A [题目大意] 有一辆限载k人速度为v2的车,n个步行速度均为v1的人要通过一段长度为l的距离 ... 
- linux 在终端中打开图形化文件管理器
			虽然终端十分强大,但在少数使用终端的时候,会突然需要图形化文件管理器的帮忙. 命令: xdg-open "dir" 例如 xdg-open ./ 用图形化文件管理器打开当前文件夹 ... 
- SQLServer 2008的组成
			SQLServer 2008的组成: 1.主要数据库文件:有且只有一个,文件后缀为.mdf. 2.日志文件:至少有一个,文件后缀为.ldf. 3.次要数据库文件:任意个,文件后缀为.ndf. 
- Device Mapper Multipath(DM-Multipath)
			Device Mapper Multipath(DM-Multipath)能够将server节点和存储阵列之间的多条I/O链路配置为一个单独的设备.这些I/O链路是由不同的线缆.交换机.控制器组成的S ... 
- SVD神秘值分解
			SVD分解 SVD分解是LSA的数学基础,本文是我的LSA学习笔记的一部分,之所以单独拿出来,是由于SVD能够说是LSA的基础,要理解LSA必须了解SVD,因此将LSA笔记的SVD一节单独作为一篇文章 ... 
- 阿里云Ubuntu部署java web(2) - 配置tomcat
			系统版本号:Ubuntu12.04 64位 安装: 首先要安装java(測试时使用的版本号是6b27-1.12.6-1ubuntu0.12.04.2).版本号可自行选择,但不同版本号配置方法可能不同. ... 
- 有关UIWebView的SSL总结
			在网上找了非常多文章差点儿相同都是一样的,基本上都是关于NSURLConnection的文章. 如今把几个比較好的连接分享给大家http://blog.csdn.net/pingchangtan367 ... 
- JS中的replace方法
			JavaScript中replace() 方法如果直接用str.replace("-","!") 只会替换第一个匹配的字符. 而str.replace(/\-/ ... 
- C# 微信公众平台开发(4)-- 模版消息
			微信公众平台开发 --发送模版消息 发送模版消息是微信服务号给某个用户发送模版消息,类似于APP的推送通知: 1.添加模版消息 在页面的左上 有一个添加功能插件的 按钮,如题 添加完成后,我们就可以在 ... 
