消息推送,就是在互联网上通过定期传送用户需要的信息来减少信息过载的一项新技术。推送技术通过自动传送信息给用户,来减少用于网络上搜索的时间。它根据用户的兴趣来搜索、过滤信息,并将其定期推给用户,帮助用户高效率地发掘有价值的信息。
一、轮询
1、短轮询
http短轮询是服务器收到请求不管是否有数据都直接响应 http 请求; 浏览器受到 http 响应隔一段时间在发送同样的 http 请求查询是否有数据;
http 短轮询的局限是实时性低;
http 长轮询是服务器收到请求后如果有数据, 立刻响应请求; 如果没有数据就会 hold 一段时间, 这段时间内如果有数据立刻响应请求; 如果时间到了还没有数据, 则响应 http 请求;浏览器受到 http 响应后立在发送一个同样 http 请求查询是否有数据;
http 长轮询的局限:
浏览器端对统一服务器同时 http 连接有最大限制, 最好同一用户只存在一个长轮询;
服务器端没有数据 hold 住连接时会造成浪费, 容易产生服务器瓶颈;
二、长连接
1、http长连接
目前 http 协议普遍使用的是 1.1 版本, 之前有个 1.0 版本, 两者之间的一个区别是 1.1 支持http 长连接, 或者叫持久连接.1.0 不支持 http 长连接, 每次一个 http 请求响应后都关闭 tcp 连接, 下个 http 请求会重新建立 tcp 连接.
所谓 http 长连接, 就是多个 http 请求共用一个 tcp 连接; 这样可以减少多次临近 http 请求导致 tcp 建立关闭所产生的时间消耗. http 1.1 中在请求头和相应头中用 connection字段标识是否是 http 长连接,connection: keep-alive, 表明是 http 长连接;connection:closed, 表明服务器关闭 tcp 连接
与 connection 对应的一个字段是keep-live, http 响应头中出现, 他的格式是 timeout=30, max=5, timeout 是两次 http 请求保持的时间(s), , max 是这个 tcp 连接最多为几个 http 请求重用。
2、tcp长连接
先说短连接, 短连接是通讯双方有数据交互时就建立一个连接, 数据发送完成后,则断开此连接。
长连接就是大家建立连接之后, 不主动断开. 双方互相发送数据, 发完了也不主动断开连接, 之后有需要发送的数据就继续通过这个连接发送。
TCP连接在默认的情况下就是所谓的长连接, 也就是说连接双方都不主动关闭连接, 这个连接就应该一直存在。
当网络通信时采用TCP协议时,在真正的读写操作之前,server与client之间必须建立一个连接,
当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,
连接的建立是需要三次握手的,而释放则需要4次握手,
所以说每个连接的建立都是需要资源消耗和时间消耗的
经典的三次握手示意图:
经典的四次握手关闭图:
推送机制:
如何获取新数据呢:
服务器端通知,客户端获取
客户端携带最新的SyncKey,发起数据请求
服务器端生成最新的SyncKey连同最新数据发送给客户端
基于版本号机制同步协议,可确保数据增量、有序传输
SyncKey,由服务器端序列号生成器生成,一旦有新消息产生,将会产生最新的SyncKey。类似于版本号
服务器端通知有状态更新,客户端主动获取自从上次更新之后有变动的状态数据,增量式,顺序式。
http://www.blogjava.net/yongboy/archive/2014/03/05/410636.html
心跳包保活
因为是长连接, 所以需要定期发送心跳包;心跳包是用来通知服务器客户端当前状态。
明确一点, TCP长连接本质上不需要心跳包来维持, 大家可以试一试, 让两台电脑连上同一个wifi, 然后让其中一台做服务器, 另一台用一个普通的没有设置KeepAlive的Socket连上服务器, 只要两台电脑别断网, 路由器也别断电, DHCP(动态主机配置协议)正常续租, 就这么放着, 过几个小时再用其中一台电脑通过之前建立的TCP连接给另一台发消息, 另一台肯定能收到。
那为什么要有心跳包呢?
NAT超时
因为IPv4地址不足, 或者我们想通过无线路由器上网, 我们的设备可能会处在一个NAT设备的后面, 生活中最常见的NAT设备是家用路由器.
NAT设备会在IP封包通过设备时修改源/目的IP地址. 对于家用路由器来说, 使用的是网络地址端口转换(NAPT), 它不仅改IP, 还修改TCP和UDP协议的端口号, 这样就能让内网中的设备共用同一个外网IP. 举个例子, NAPT维护一个类似下表的NAT表:
NAT设备会根据NAT表对出去和进来的数据做修改, 比如将192.168.0.3:8888发出去的封包改成120.132.92.21:9202, 外部就认为他们是在和120.132.92.21:9202通信. 同时NAT设备会将120.132.92.21:9202收到的封包的IP和端口改成192.168.0.3:8888, 再发给内网的主机, 这样内部和外部就能双向通信了, 但如果其中192.168.0.3:8888 == 120.132.92.21:9202这一映射因为某些原因被NAT设备淘汰了, 那么外部设备就无法直接与192.168.0.3:8888通信了。
我们的设备经常是处在NAT设备的后面, 比如在大学里的校园网, 查一下自己分配到的IP, 其实是内网IP, 表明我们在NAT设备后面, 如果我们在寝室再接个路由器, 那么我们发出的数据包会多经过一次NAT.
国内移动无线网络运营商在链路上一段时间内没有数据通讯后, 会淘汰NAT表中的对应项, 造成链路中断。
网络状态切换
手机网络和WIFI网络切换, 网络断开和连上等情况, 也会使长连接断开. 这里原因可能比较多, 但结果无非就是IP变了, 或者被系统通知连接断了.
DHCP(动态主机配置协议)的租期
目前测试发现安卓系统对DHCP的处理有Bug, DHCP租期到了不会主动续约并且会继续使用过期IP, 这个问题会造成TCP长连接偶然的断连。
其实主要是为了防止上面提到的NAT超时, 既然一些NAT设备判断是否淘汰NAT映射的依据是一定时间没有数据, 那么客户端就主动发一个数据。
当然, 如果仅仅是为了防止NAT超时, 可以让服务器来发送心跳包给客户端, 不过这样做有个弊病就是, 万一连接断了, 服务器就再也联系不上客户端了. 所以心跳包必须由客户端发送, 客户端发现连接断了, 还可以尝试重连服务器。
所以心跳包的主要作用是防止NAT超时, 其次是探测连接是否断开。
心跳包的时间间隔
既然心跳包的主要作用是防止NAT超时, 那么这个间隔就大有文章了。
发送心跳包势必要先唤醒设备, 然后才能发送, 如果唤醒设备过于频繁, 或者直接导致设备无法休眠, 会大量消耗电量, 而且移动网络下进行网络通信, 比在wifi下耗电得多. 所以这个心跳包的时间间隔应该尽量的长, 最理想的情况就是根本没有NAT超时, 比如刚才我说的两台在同一个wifi下的电脑, 完全不需要心跳包. 这也就是网上常说的长连接, 慢心跳。
根据网上的一些说法, 中移动2/3G下, NAT超时时间为5分钟, 中国电信3G则大于28分钟, 理想的情况下, 客户端应当以略小于NAT超时时间的间隔来发送心跳包。
wifi下, NAT超时时间都会比较长, 据说宽带的网关一般没有空闲释放机制, GCM有些时候在wifi下的心跳比在移动网络下的心跳要快, 可能是因为wifi下联网通信耗费的电量比移动网络下小。
守护服务
1、系统闹铃服务定时发广播检查;
2、监听网络变化、屏幕唤醒;