手機上的消息推送


最近在找android手機上的消息推送的解決方案。目前看來有以下幾種常用的方式:

1.定期查詢:按照指定的時間間隔連接服務器查詢獲取最新的消息。實現起來簡單,非實時,查詢時間過短則流量耗費多,耗電量大。下面是一個愛立信的測試結果:

 

2.短信方式:需要及時發送消息給客戶端時也可以通過這種方式,但大家都懂的,這個很花錢。

 

3.長輪詢:基本上與目前很多網站使用的方式一樣(WEB阿里旺旺、微博、人人等等)。客戶端發起一個很長超時時間的請求,然后服務器端在沒有消息的時候阻塞這個請求(一直不給返回值)直到快要超時為止,有消息到來再返回響應。客戶端收到響應或超時后立即再發起請求。

這種算是比較好的方式了,消息能夠及時地到達客戶端。但考慮到移動互聯網的特點(網絡不穩定、設備內存小)這種方式不能保證重要的消息一定能推送到客戶端,另外anroid在手機內存小的情況下可能會殺這個在等待PUSH消息不怎么活動的進程。

 

4.C2DM:GOOGLE提供了消息的PUSH功能,需要和GOOGLE賬號綁定,目前看來這種方式在國內是沒戲的。

 

5.XMPP:在客戶端集成asmack,服務器端使用ejabberd或openfire等開源的XMPP服務器軟件也是一種可行的方式。

缺點就是先要有注冊、登陸等過程,無線網絡環境下連接的效果不怎么樣。重要消息的PUSH需要自己實現確認邏輯。

 

6.MQTT:基於代理發布/訂閱 模式的消息傳輸協議,適用於受限環境:

    網絡代價昂貴、帶寬低、不可靠;

    在嵌入設備中運行、處理器和內存資源有限。

特點是:

   使用發布/訂閱模式,解除應用程序耦合;

   對負載內容屏蔽的消息傳輸;

   使用TCP/IP;

   提供“至多一次”、“至少一次”、“有且僅有一次”三種級別的消息傳輸;

   小型傳輸、流量開銷少;

   使用LAST WILL 和TESTAMENT特性通知有關各方客戶端異常中斷機制。

聽起來簡直就是為移動互聯網設計的

下面是基於MQTT的簡單實現方案:

 

服務器:

可以采用IBM的MQTT服務器RSMB;

開源的Mosquitto

 

客戶端:

IBM的wmqtt.jar 適用於JAVA客戶端。

 

1.下載安裝運行Mosquitto服務器。

2.在anroid客戶端集成以下代碼:

 

import com.ibm.mqtt.IMqttClient;
import com.ibm.mqtt.MqttClient;
import com.ibm.mqtt.MqttException;
import com.ibm.mqtt.MqttPersistence;
import com.ibm.mqtt.MqttPersistenceException;
import com.ibm.mqtt.MqttSimpleCallback;

public  class MQTTConnection  implements MqttSimpleCallback{
    IMqttClient mqttClient =  null;    
     private  static  int MQTT_PORT =1883; 
     private  static MqttPersistence MQTT_PERSISTENCE= null;
     public  static String MQTT_CLIENT_ID ="";
     private  static  boolean MQTT_CLEAN_START =  true;
     private  static  short MQTT_KEEP_ALIVE = 60 * 15;
     private  static  int[] MQTT_QUALITIES_OF_SERVICE = { 0 } ;
     private  long mStartTime;
        
     public MQTTConnection(String brokerHostName, String initTopic)  throws MqttException {
        String mqttConnSpec = "tcp://" + brokerHostName + "@" + MQTT_PORT;
         //  Create the client and connect
        mqttClient = MqttClient.createMqttClient(mqttConnSpec, MQTT_PERSISTENCE);
        String clientID = MQTT_CLIENT_ID;
        mqttClient.connect(clientID, MQTT_CLEAN_START, MQTT_KEEP_ALIVE);

         //  register this client app has being able to receive messages
        mqttClient.registerSimpleHandler( this);
        
         //  Subscribe to an initial topic, which is combination of client ID and device ID.
        subscribeToTopic(initTopic);

         //  Save start time
        mStartTime = System.currentTimeMillis();
         //  Star the keep-alives
        
// startKeepAlives();            
    }
    
     private  void subscribeToTopic(String topicName)  throws MqttException {
        
         if ((mqttClient ==  null) || (mqttClient.isConnected() ==  false)) {
             //  quick sanity check - don't try and subscribe if we don't have
            
//   a connection
            System.out.println("subscribe to topic fail");
        }  else {                                    
            String[] topics = { topicName };
            mqttClient.subscribe(topics, MQTT_QUALITIES_OF_SERVICE);
        }
    }    
    
     public  void disconnect() {
         try {            
            mqttClient.disconnect();
        }  catch (MqttPersistenceException e) {
            System.out.println("disconnection to server error");
        }
    }

    
    @Override
     public  void connectionLost()  throws Exception {
         //  TODO Auto-generated method stub
        System.out.println("connection to server closed");
    }

    @Override
     public  void publishArrived(String topicName,  byte[] payload,  int qos,  boolean retained)
             throws Exception {
         //  TODO Auto-generated method stub
        String s =  new String(payload);
        System.out.println("push message recived :"+s);
    }
}

 

 

3.運行客戶端程序,在命令窗口中使用Mosquitto_pub.exe -q [Qos級別] -t [主題] -m [發布的內容] 進行測試。

 

另:Mosquitto由於使用socket select 模型,能支持的客戶端連接數量有限。

如果要支持更高並發量,一方面可以考慮采用“策略服務器+Mosquitto集群”的方式,另一方面可以考慮erlang實現的一些MQTT服務器替換Mosquitto(上次見到的一個類似的發布/訂閱系統每秒可以完成向40K訂閱用戶廣播的任務,夠牛逼了吧)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM