在写之前,我们首先了解一下为什么android维护长连接需要心跳机制,首先我们知道,维护任何一个长连接都需要心跳机制,客户端发送一个心跳给服务器,服务器给客户端一个心跳应答,这样就形成客户端服务器的一次完整的握手,这个握手是让双方都知道他们之间的连接是没有断开,客户端是在线的。如果超过一个时间的阈值,客户端没有收到服务器的应答,或者服务器没有收到客户端的心跳,那么对客户端来说则断开与服务器的连接重新建立一个连接,对服务器来说只要断开这个连接即可。那么在智能手机上的长连接心跳和在Internet上的长连接心跳有什么不同的目的呢?原因就在于智能手机使用的是移动无线网络,那么我们在讲长连接之前我们首先要了解无线移动网络的特点。

1.无线移动网络的特点:

当一台智能手机连上移动网络时,其实并没有真正连接上Internet,运营商分配给手机的IP其实是运营商的内网IP,手机终端要连接上Internet还必须通过运营商的网关进行IP地址的转换,这个网关简称为NAT(NetWork Address Translation),简单来说就是手机终端连接Internet 其实就是移动内网IP,端口,外网IP之间相互映射。相当于在手机终端在移动无线网络这堵墙上打个洞与外面的Internet相连。原理图如下:(来源网络)

GGSN(GateWay GPRS Support Note 网关GPRS支持节点)模块就实现了NAT功能,由于大部分的移动无线网络运营商为了减少网关NAT映射表的负荷,如果一个链路有一段时间没有通信时就会删除其对应表,造成链路中断,正是这种刻意缩短空闲连接的释放超时,原本是想节省信道资源的作用,没想到让互联网的应用不得以远高于正常频率发送心跳来维护推送的长连接。这也是为什么会有之前的信令风暴,微信摇收费的传言,因为这类的应用发送心跳的频率是很短的,既造成了信道资源的浪费,也造成了手机电量的快速消耗。

2.android系统的推送和IOS的推送有什么区别:

首先我们必须知道,所有的推送功能必须有一个客户端和服务器的长连接,因为推送是由服务器主动向客户端发送消息,如果客户端和服务器之间不存在一个长连接那么服务器是无法来主动连接客户端的。因而推送功能都是基于长连接的基础是上的。

IOS长连接是由系统来维护的,也就是说苹果的IOS系统在系统级别维护了一个客户端和苹果服务器的长链接,IOS上的所有应用上的推送都是先将消息推送到苹果的服务器然后将苹果服务器通过这个系统级别的长链接推送到手机终端上,这样的的几个好处为:1.在手机终端始终只要维护一个长连接即可,而且由于这个长链接是系统级别的不会出现被杀死而无法推送的情况。2.省电,不会出现每个应用都各自维护一个自己的长连接。3.安全,只有在苹果注册的开发者才能够进行推送,等等。

android的长连接是由每个应用各自维护的,但是google也推出了和苹果技术架构相似的推送框架,C2DM,云端推送功能,但是由于google的服务器不在中国境内,其他的原因你懂的。所以导致这个推送无法使用,android的开发者不得不自己去维护一个长链接,于是每个应用如果都24小时在线,那么都得各自维护一个长连接,这种电量和流量的消耗是可想而知的。虽然国内也出现了各种推送平台,但是都无法达到只维护一个长连接这种消耗的级别。

3.推送的实现方式:

一:客户端不断的查询服务器,检索新内容,也就是所谓的pull 或者轮询方式

二:客户端和服务器之间维持一个TCP/IP长连接,服务器向客户端push

三:服务器又新内容时,发送一条类似短信的信令给客户端,客户端收到后从服务器中下载新内容,也就是SMS的推送方式

苹果的推送系统和googleC2DM推送系统其实都是在系统级别维护一个TCP/IP长连接,都是基于第二种的方式进行推送的。第三种方式由于运营商没有免费开放这种信令导致了这种推送在成本上是无法接受的,虽然这种推送的方式非常的稳定,高效和及时。

如果想了解android中各种推送方式请参考这个链接:Android实现推送方式解决方案 这篇博客已经介绍的非常好了。

所谓的心跳包就是客户端定时放送简单的信息给服务器端,告诉它我还在而已。代码就是每隔几分钟发送一个固定信息给服务器端,服务器端回复一个固定信息。如果服务器端几分钟后没有收到客户端信息则视客户端断开。比如有些通信软件长时间不适用,要想知道它的状态是在线还是离线,就需要心跳包,定时发包收包。

心跳包之所以叫心跳包是因为:它像心跳一样每隔固定时间发一次,以此来告诉服务器,这个客户端还活在。事实上这是为了保持长连接,至于这个包的内容,是没有什么特别规定的,不过一般都是很小的包,或者只包含包头的一个空包。

在TCP机制里面,本身是存在有心跳包机制的,也就是TCP选项:SO_KEEPALIVE. 系统默认是设置的2小时的心跳频率。

Socket长连接+心跳检测:

http://blog.csdn.net/zh724738989/article/details/42007099

或者本博客:https://blog.csdn.net/yh199610/article/details/120033894?spm=1001.2014.3001.5502

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

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

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

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

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;@Overridepublic 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();}}

最近做项目用到心跳轮询到主动到服务器取消息,为了做推送。坑了个爹的,极光百度推送限制多不能满足需求,只能自己写…手机主动到Service取数据,也就意味着你的手机要有一个服务,一直在后台运行,在特定的时间去服务器询问有没有消息,如果有消息则取回客户端。 
当然还可以用像什么XMPP(当然为了一个消息推送,动用那么大而又笨重的东西,很明显不明智),短信通知等等一下方式。

这里主要讲在android主动取数据: 
其实实现后台推送消息给客户端可以分为主动取,和主动推两种。

主动取:就是我们上面说的轮询服务器取消息。 
主动推:服务器推送消息给客户端,这里必须客户端和服务器保持长连接。 
两种形式各有利弊,“主动取”不能保证消息的实时性;“主动推”能保证消息的实时性,但是不能保证android端的这个链接不会被kill掉。

实现轮询

  • 原理 
    其原理在于在android端的程序中,让一个SERVICE一直跑在后台,在规定时间之内调用服务器接口进行数据获取。

    这里的原理很简单,当然实现起来也不难;

    然后,这个类之中肯定要做网络了数据请求,所以我们在Service中建立一个线程(因为在android系统中网络请求属于长时间操作,不能放主线程,不然会导致异常),在线程中和服务器进行通信。

    最后,这个逻辑写完后,我们需要考虑一个问题,如何进行在规定时间内调用该服务器,当然可以用Thread+Handler(这个不是那么稳定),也可以使用AlamManager+Thread(比较稳定),因为我们需要其在后台一直运行,所以可以依靠系统的Alammanager这个类来实现,Alammanager是属于系统的一个闹钟提醒类,通过它我们能实现在规定间隔时间调用,并且也比较稳定,这个service被杀后会自己自动启动服务。

出于最近对im研究的兴趣,看到smack里有个30s发送一个空消息的线程,了解了下关于心跳包,keepalive的知识。 TCP的socket本身就是长连接的,那么为什么还要心跳包呢?

搜索到的资料解释如下:

一:内网机器如果不主动向外发起连接,外网机没法直连内网的,这也是内网机安全的原因之一吧,又因为路由器会把这个关系记录下来,但是过一段时间这个记录可能会丢失 ,所有每一个客户端每隔一定时间就会向服务器发送消息,以保证服务器可以随时找到你,这东西被称为心跳包。

二:理论上说,这个连接是一直保持连接的,但是实际情况中,如果中间节点出现什么故障是难以知道的。更要命的是,有的节点(防火墙)会自动把一定时间之内没有数据交互的连接给断掉。在这个时候,就需要我们的心跳包了,用于维持长连接,保活。在获知了断线之后,服务器逻辑可能需要做一些事情,比如断线后的数据清理呀,重新连接呀……当然,这个自然是要由逻辑层根据需求去做了。总的来说,心跳包主要也就是用于长连接的保活和断线处理。一般的应用下,判定时间在30-40秒比较不错。如果实在要求高,那就在6-9秒。

三:

<span style="font-size: 18px;"><span style="color:#333333;">如果不主动关闭socket的话,系统不会自动关闭的,除非当前进程挂掉了,操作系统把占用的socket回收了才会关闭。为什么需要心跳连接主要是判断当前连接是否是有效的、可被使用的。在实际应用中假设一段时间没有数据传输时候理论上说应该连接是没有问题的,但是网络复杂,中途出现问题也是常见的,网线被掐断了、对方进程挂掉了、频繁丢包等,这时候TCP连接是不可使用的,但是对于应用层并不知道,如果需知道网络情况则要很复杂的超时进行了解,TCP从底层就实现了这样的功能。</span><span style="color:#009900;"><strong>心跳机制</strong></span><span style="color:#333333;">是TCP在一段时间间隔后发送确定连接端是否还存在,如果存在的话就会回传一个包确定网络有效,如果心跳包有问题,则通知上层应用当前网络有问题了。</span></span>
<span style="font-size: 18px;"><span style="font-family: arial, 宋体, sans-serif; line-height: 24px;"></span></span><pre class="reply-text mb10" id="content-886462114" name="code" style="white-space: pre-wrap; word-wrap: break-word; margin-top: 0px; margin-bottom: 10px; padding: 0px; font-family: Arial; zoom: 1;"><span style="font-size: 18px;">这取决于你的server端的超时配置, 每个socket连接都是长连接,它是一个相当占用系统资源的通信管道, 如果这个长连接什么事也没干硬是要占着资源,则server端可以选择关闭这个连接,以省下资源让更多的用户连接进来。
所以,即便客户端的是采用死循环while(true)方式连到服务端,对于特定的客户端和服务端类型来说也需要一定时间间隔的心跳(告诉服务端,我还活着,虽然我没干活也没说话,但别把我关了)。</span>
<span style="font-size: 18px;">记得以前开发手机游戏时,索爱有一款手机有强制要求,客户端如果超过三分钟无消息发向网络服务端,则会在客户端自动地强制把socket关断。因为socket长连接相对于手机这样资源少的设备来说是宝贵的资源。  (这个强制是指客户端系统自动关的,不是我们代码close的) </span>

这3个原因都是挺有道理。如果你有更好的解释欢迎交流啊。改天我做个程序测试一下不发心跳包和发心跳包的连接情况。

来源:1.http://blog.csdn.net/qgjava/article/details/5745776

2.http://topic.csdn.net/u/20081009/13/abd12947-e78e-43ba-9a43-ce690ecb8ac2.html

3.http://zhidao.baidu.com/question/349886234.html

Android长连接心跳机制相关推荐

  1. 转 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    http://blog.csdn.net/zhangzeyuaaa/article/details/39028369 目录(?)[-] 无线移动网络的特点 android系统的推送和IOS的推送有什么 ...

  2. mqtt如何发送心跳 安卓_互联网推送服务原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  3. 互联网推送服务原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  4. [心跳] 互联网推送服务原理:长连接+心跳机制

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  5. 移动互联网消息推送原理:长连接+心跳机制(MQTT协议)

    互联网推送消息的方式很常见,特别是移动互联网上,手机每天都能收到好多推送消息,经过研究发现,这些推送服务的原理都是维护一个长连接(要不不可能达到实时效果),但普通的socket连接对服务器的消耗太大了 ...

  6. Netty(一) SpringBoot 整合长连接心跳机制

    https://github.com/crossoverJie/JCSprout 原创: crossoverJie 阅读原文 前言 Netty 是一个高性能的 NIO 网络框架,本文基于 Spring ...

  7. 长连接-心跳保活机制

    前言 当实现具备实时性需求时,我们一般会选择长连接的通信方式 而在实现长连接方式时,存在很多性能问题,如 长连接保活 今天,我将 手把手教大家实现自适应的心跳保活机制,从而能高效维持长连接 目录 1. ...

  8. php 长连接心跳_支持gRPC长链接,深度解读Nacos2.0架构设计及新模型

    作者 | 杨翊(席翁) Nacos PMC 来源|阿里巴巴云原生公众号 Nacos 简介 Nacos 在阿里巴巴起源于 2008 年五彩石项目,该项目完成了微服务拆分和业务中台建设,随着云计算和开源环 ...

  9. 长连接心跳问题解决总结

    一.长连接的定义与心跳说明 我们在客户端(手机APP.浏览器.电脑客户端等)去向服务器请求数据交互的时候,一般是通过网络进行消息的传输.其中依据网络传输协议,与服务器建立的连接都是基于TCP/UDP进 ...

最新文章

  1. MySQL必知必会读书笔记
  2. Github 热榜项目:如何让你的终端酷炫到没朋友
  3. 软件开发的MVC构架
  4. [js] setTimeout的第三个参数有什么用?
  5. 什么是指利用计算机和现代,现代计算机一般指什么计算机?
  6. uTorrent for mac(BT下载客户端)v1.8.7中文版
  7. http请求过程_“HTTP请求的整个过程”与它引出了整个计算机网络知识图谱(一)...
  8. CCF NOI1012 变换密码
  9. HTML案例登录页面
  10. 超强大几十款功能组合而成的一款工具箱微信小程序源码下载支持N个流量主
  11. 笔记本电脑怎么找计算机硬盘,如何给笔记本电脑硬盘分区
  12. 【专项研究】支付宝会员积分体系
  13. linux 软件放什么目录,Linux 下的各种目录
  14. 使用搜索引擎时如何去除广告推荐
  15. 微信撤回服务器有没有,无需任何软件, 告诉你如何查看微信撤回的图片!
  16. linux导入iou iol的方法,网络实验环境搭建--3.如何使用IOL/IOU
  17. 有两个关系S(A, B, C, D)和T(C, D,E, F), 写出与下列查询等价的SQL表达式:
  18. android自动屏幕点击事件,Android 中屏幕点击事件的实现
  19. 百元级冷门高音质蓝牙耳机推荐,300左右为什么不试试这几款蓝牙耳机?
  20. ginkgo php,ginkgo: ginkgo 是一个免费开源的轻量级 PHP 开发框架

热门文章

  1. kafka简介及应用场景、架构
  2. 合创视觉科技UI设计师就业发展前景怎么样?薪资待遇如何?
  3. 混子日记——校园征信项目1
  4. 从写简历,到面试,到谈薪酬的那些技巧和防坑指南
  5. SQL注入——堆叠注入入门题:领取 iPad Pro
  6. 多玩我的世界java异常_应用程序发生异常 未知的软件异常解决办法大全
  7. 基于airtest+poco微信服务号自动化测试NO1
  8. 微信如何实现自动跳转到用其他浏览器打开指定页面
  9. ChatGPT:人工智能助手的新时代
  10. vim python 函数跳转_vim跳转(示例代码)