[转]宝文!Apple Push Notification Service (APNS)原理与实现方案
原理
簡單的說,app要單獨實現消息動態更新,一種是輪詢,這對用戶來說會帶來額外的流量。另一種方案是push,app client和server直接保持一個長連接,有新的消息時server push給app client。
這兩種通過app自身實現的“push”都會面臨以下問題:
APNS為app開發商提供了一個統一的消息通知平臺。apple和每個iOS設備之間保持一個長連接。開發商將消息發送給APNS,APNS將該消息發送到指定的iOS設備,iOS設備展示消息、啟動相應的app。
從以上過程可知,為通過APNS實現消息push,一個消息需要標識發送到“哪臺iOS設備”的“哪個app”。這兩個分別由設備id(deviceToken)和SSL的證書文件(開啟消息push的app需要配置一個SSL證書)標識。消息結構體如下:
實現方案
詳細過程請參考http://mobiforge.com/developing/story/programming-apple-push-notification-services,一步步來即可。這一過程會生成文件:
雙擊aps_developer_identity.cer將證書文件導入到Keychain Access。
java/php/c++需要的SSL證書和密鑰生成如下:
| 1 | openssl pkcs12 -in [xxx].p12 -out [xxx].pem -nodes |
將最終生成的pem文件提供給后臺server
后臺代碼示例
app client請參考上述鏈接中的示例。
push server:
object c版本?http://stefan.hafeneger.name/download/PushMeBabySource.zip
java版本?http://code.google.com/p/javapns/
php版本?http://code.google.com/p/apns-php/
現在后臺技術主要還是c/c++吧,網上一直沒找到合適的,自己實現demo,代碼如下:
/*** @file main.cpp* @author Maxwin* @description TestPushServer*/#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <openssl/ssl.h> #include <openssl/rand.h> #include <openssl/bio.h> #include <openssl/err.h> #include <openssl/x509.h>#include <netinet/in.h>// 證書文件 #define CERTFILE "max.pem"SSL *ssl; SSL_CTX *ctx;void error(const char *msg) {printf("[ERROR]:%s\n", msg);exit(1); }SSL_CTX *setup_client_ctx() {ctx = SSL_CTX_new(SSLv23_method());if (SSL_CTX_use_certificate_chain_file(ctx, CERTFILE) != 1) {error("Error loading certificate from file\n");}if (SSL_CTX_use_PrivateKey_file(ctx, CERTFILE, SSL_FILETYPE_PEM) != 1) {error("Error loading private key from file\n");}return ctx; }// 將deviceToken字符串轉成對應的binary bytes void token2bytes(const char *token, char *bytes) {int val;while (*token) {sscanf(token, "%2x", &val);*(bytes++) = (char)val;token += 2;while (*token == ' ') { // skip space++token;}} }// 打包消息 unsigned long packMessage(char *message, const unsigned char command, const char *tokenBytes, const char *payload) {unsigned long payloadLength = strlen(payload);unsigned short networkTokenLength = htons(32);unsigned short networkPayloadLength = htons(payloadLength);memcpy(message, &command, sizeof(unsigned char));message += sizeof(unsigned char);memcpy(message, &networkTokenLength, sizeof(unsigned short));message += sizeof(unsigned short);memcpy(message, tokenBytes, 32);message += 32;memcpy(message, &networkPayloadLength, sizeof(unsigned short));message += sizeof(unsigned short);memcpy(message, payload, payloadLength);return payloadLength + 37; }int push(const char *token, const char *payload) {char tokenBytes[32];char message[293];unsigned long msgLength;token2bytes(token, tokenBytes);msgLength = packMessage(message, 0, tokenBytes, payload);return SSL_write(ssl, message, (int)msgLength); }int main (int argc, const char * argv[]) {char token[] = "2b2474e5 ac7670f3 08fabf3a 9c1d1295 ed50e9aa f11b941a d6e3d213 4f535408";char payload[] = "{\"aps\":{\"alert\":\"Hello world!!!\",\"badge\":1}}";char payload2[] = "{\"aps\":{\"alert\":\"Hello kitty!!!\",\"badge\":12}}";char host[] = "gateway.sandbox.push.apple.com:2195";BIO *conn;// initSSL_library_init();ctx = setup_client_ctx();conn = BIO_new_connect(host);if (!conn) {error("Error creating connection BIO\n");}if (BIO_do_connect(conn) <= 0) {error("Error connection to remote machine");}if (!(ssl = SSL_new(ctx))) {error("Error creating an SSL contexxt");}SSL_set_bio(ssl, conn, conn);if (SSL_connect(ssl) <= 0) {error("Error connecting SSL object");}printf("SSL Connection opened\n");// push messageint ret = push(token, payload);printf("push ret[%d]\n", ret);// push [Hello kitty] after 5ssleep(5);ret = push(token, payload2);printf("push2 ret[%d]\n", ret);printf("Close SSL Connection\n");SSL_shutdown(ssl);SSL_free(ssl);SSL_CTX_free(ctx);return 0; }
編譯運行:
g++ main.cpp -o pushServer -lssl -lcrypto
?
轉載于:https://www.cnblogs.com/lihaozy/archive/2013/02/25/2931860.html
總結
以上是生活随笔為你收集整理的[转]宝文!Apple Push Notification Service (APNS)原理与实现方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全文检索技术介绍与使用方法
- 下一篇: c# mysql varbinary_c