其實服務端與客戶端實現消息推送的方式有幾種:
1、客戶端不斷的查詢服務器,檢查新的內容,也就是所謂的pull或者輪詢的方式;
2、客戶端與服務器之間維持一個TCP/IP長連接(在HTTP1.1中,所有的請求都認為是長連接),服務器向客戶端push;
3、當服務端有新內容的時候,發送一條類似短信的信令給客戶端,客戶端收到貨從服務器下載新內容,也就是SMS的推送方式;
對於第一種方式有以下的缺點:
1、因為需要不斷地輪詢,所以手機會很耗電;
2、容易被系統殺死;
對於第二種方式:
我們首先來了解一下HTTP長連接的相關知識:
在HTTP1.1中,所有的鏈接都認為是長連接;HTTP長連接是一個在TCP連接的基礎上,發送多個HTTP請求以及接收多個HTTP響應,這是為了避免每一次請求都去打開一個新的連接
在這裡的消息推送系統中,HTTP長連接的作用就是向服務器發送請求,然後一直等待服務器的返回數據;這就相當於客戶端在“監聽”服務器,可以隨時收到來自服務器的消息。
在這裡還涉及到了同步與異步、阻塞與非阻塞等相關知識:
同步:IO操作將導致請求進程阻塞,知道IO操作完成,也就是說客戶端在發送請求之後,必須得在服務端有回應之後才發送下一個請求;
異步:IO操作不導致請求進程阻塞,也就是說客戶端在發送請求之後,不必等待服務端的回應就可以發送下一個請求;
阻塞:服務端的線程或者進程沒有處理完數據的時候,不會返回,線程或者進程會被掛起,不再相應其他請求;
非阻塞:服務器端在沒有處理完的時候會立即返回,不會掛起 線程或者進程,可以繼續響應其他的請求;
阻塞和非阻塞是服務器端對請求的處理方式,在消息推送系統中,客戶端+服務器一起,使用的是異步非阻塞。
1、客戶端發出一個http長連接請求,然後等待服務端的響應,這個請求是異步的,所以客戶端可以繼續其他工作,比如發起其他的ajax請求等等。
2、服務端接到請求之後,並不立即發出數據,而是hold住這個連接,這個處理是非阻塞的,所以服務器還可以處理其他的請求;
3、在某個時刻,服務器有新的數據了,服務器再主動把這個消息推送出去,即通過之前建立的連接將數據推送給客戶端;
4、客戶端收到返回,這個時候就可以處理數據了,同時再次發起新的長連接。
而對於移動端來說:
首先說android端的:
普通的socket連接對服務器的消耗太大,所以就出現了像MQTT這種輕量級低消耗的協議來維護長連接;android維護長連接需要心跳機制,客戶端發送一個心跳給服務器,服務器給客戶端一個心跳應答,這樣就形成了一次完整的握手,這個握手讓雙方都知道他們之間的連接沒有斷開,客戶端是在線的。如果超過一個時間的閥值,客戶端沒有收到服務器的應答或者服務器沒有收到客戶端的心跳,那麼對客戶端來說則斷開與服務器的連接重新建立一個連接,對服務器來說只要斷開這個連接即可。
android的長連接是由每個應用各自維護的,於是每個應用如果在24小時在線,那麼都得各自維護一個長連接,這種電量的消耗是可想而知的。
接下來對於IOS的:
IOS長連接是由系統維護的,也就是說蘋果的ios系統在系統級別維護了一個客戶端與蘋果服務器的長連接,ios的所有應用上的推送都是先將消息推送到蘋果的服務器,然後蘋果的服務器通過這個系統級別的長連接推送到手機端上,這樣有幾個好處:
1、在手機終端始終只要維護一個長連接即可,而且由於這個長連接是系統級別的,不會出現被殺死而無法推送的情況;
2、省電,不會出現每個應用都各自維護一個自己的長連接;
3、安全,只有在蘋果注冊的開發者才能進行推送;
在這裡解釋一下MQTT協議:
輕量級的machine-to-machine通信協議;
publish/subscribe模式(發布訂閱模式)
基於tcp/ip
支持Qos
適合於低寬帶、不可靠連接、嵌入式設備、cpu內存資源緊張;
是一種比較不錯的android消息推送方案
FacebookMessager采用了MQTT