iOS 进阶开发— 原生APNS配置以及server实现(c++版本)

来源:互联网 发布:武汉矩阵互动科技抄袭 编辑:程序博客网 时间:2024/06/05 03:44

关于iOS APNS的server provider 一直没有看到关于c++版本的,不过现在的各种第三方APNS已经很成熟了,比如百度的云推送SDK等等,这里简单总结一下如何实现iOS原生的APNS server provider.

第一步,生成证书,如何生成.p12证书这里就不细说了,如果不清楚的请查阅其他文档,或者评论里留言,如果问的多的话我再加上

openssl pkcs12 -clcerts -nokeys -out cert.pem -in Certificate.p12 provide new password if asked. openssl pkcs12 -nocerts -out key.pem -in Certificate.p12 provide new password if asked. cat cert.pem key.unencrypted.pem > ck.pem

测试版本要生成developer 证书,发布的要对应的生成发布版本的。

生成.pem证书之后,把pem证书放到你的server provider工程中去。

第二步:server provider实现(c++版本)

要实现server provider, 需要先编译安装openssl, 因为Apple 的APNS是基于openssl实现的。

先来看头文件实现

/* * Auth The Croods */#pragma once#include <stdio.h>#include <tchar.h>#include <stdlib.h>#include <winsock.h>#include <openssl/ssl.h>#include <openssl/rand.h>#include <openssl/bio.h>#include <openssl/err.h>#include <openssl/x509.h>// certificate#define CERTFILE "./apns_dev.pem"#define SSL_CTX_LOAD_VERIFY_LOCATIONS_FAILED  -1#define BIO_DO_CONNECT_FAILED                 -2#define SSL_GET_VERIFY_RESULT_FAILED          -3class APNS_Croods{private:    SSL_CTX                *m_pctx;    SSL                    *m_pssl;    const SSL_METHOD       *m_pmeth;    X509                   *m_pserver_cert;    EVP_PKEY               *m_pkey;    BIO *bio;public:    APNS_Croods(void);    ~APNS_Croods(void);    int APNS_protal();    void Reset();    int pushmessage(const char *token, const char *payload);    void token2bytes(const char *token, char *bytes);};
接下来看类实现:

#include "APNS_Croods.h"APNS_Croods::APNS_Croods(void){    m_pctx            = NULL;    m_pssl            = NULL;    m_pmeth            = NULL;    m_pserver_cert    = NULL;    m_pkey            = NULL;    bio                = NULL;}APNS_Croods::APNS_Croods(void){    Reset();}int APNS_Croods::pushmessage(const char *token, const char *payload){    char tokenBytes[32];    char message[293];    int msgLength;        token2bytes(token, tokenBytes);        unsigned char command = 0;    size_t payloadLength = strlen(payload);    char *pointer = message;    unsigned short networkTokenLength = htons((u_short)32);    unsigned short networkPayloadLength = htons((unsigned short)payloadLength);    memcpy(pointer, &command, sizeof(unsigned char));    pointer +=sizeof(unsigned char);       memcpy(pointer, &networkTokenLength, sizeof(unsigned short));     pointer += sizeof(unsigned short);    memcpy(pointer, tokenBytes, 32);    pointer += 32;    memcpy(pointer, &networkPayloadLength, sizeof(unsigned short));    pointer += sizeof(unsigned short);    memcpy(pointer, payload, payloadLength);    pointer += payloadLength;    msgLength = (int)(pointer - message);    int ret = SSL_write(m_pssl, message, msgLength);    return ret;}int APNS_Croods::APNS_protal(){    //    char token[] = "8da412ec d60b4a8d ea08a8f5 31f0e832 ba87c072 8920cf7d 2e436f40 c367205b";    char payload[] = "{\"aps\":{\"alert\":\"Hello world!!! message from c++\",\"badge\":1}}";        char host[] = "gateway.sandbox.push.apple.com:2195";    /*    * Lets get nice error messages    */    SSL_load_error_strings();    ERR_load_BIO_strings();    OpenSSL_add_all_algorithms();    /*    * Setup all the global SSL stuff    */    SSL_library_init();    m_pctx = SSL_CTX_new(SSLv23_client_method());    if (SSL_CTX_use_certificate_chain_file(m_pctx, CERTFILE) != 1) {         printf("Error loading certificate from file\n");          return -1;    }        if (SSL_CTX_use_PrivateKey_file(m_pctx, CERTFILE, SSL_FILETYPE_PEM) != 1) {           printf("Error loading private key from file\n");           return -2;    }    bio = BIO_new_connect(host);    if (!bio) {          printf("Error creating connection BIO\n");         return -3;    }    if (BIO_do_connect(bio) <= 0) {           printf("Error connection to remote machine\n");          return -4;    }    if (!(m_pssl = SSL_new(m_pctx))) {          printf("Error creating an SSL contexxt\n");           return -5;    }    SSL_set_bio(m_pssl, bio, bio);    int slRc = SSL_connect(m_pssl);    if (slRc <= 0) {        printf("Error connecting SSL object>>%d\n", slRc);        return -6;    }    int ret = pushmessage(token,payload);      printf("push ret[%d]\n", ret);    Reset();    return 0;}// change deviceToken string to binary bytesvoid APNS_Croods::token2bytes(const char *token, char *bytes){    int val;    while (*token) {        sscanf_s(token, "%2x", &val);        *(bytes++) = (char)val;        token += 2;        while (*token == ' ') {            // skip space            ++token;        }    }}void APNS_Croods::Reset(){    if(m_pssl)    {        SSL_shutdown(m_pssl);        SSL_free(m_pssl);        m_pssl = NULL;    }    if(m_pctx)    {        SSL_CTX_free(m_pctx);        m_pctx = NULL;    }}

注意:
char host[] = "gateway.sandbox.push.apple.com:2195";
这是apple APNS的developer 接口,如果是发布的话,要改成相应的发布接口,具体官网查询一下吧


下边接着来看,iOS客户端应用如何实现程序启动时读取通知内容:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    

NSDictionary * remoteNotification = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];    NSLog(@">>>>remoteNotification>>%@>>>>>launchOptions>>>%@", remoteNotification,launchOptions);    if (remoteNotification!=nil) {        NSLog(@">>>>remoteNotification.userInfo>>%@", [[remoteNotification objectForKey:@"aps"]objectForKey:@"alert"]);        NSString *alertBody = [[remoteNotification objectForKey:@"aps"]objectForKey:@"alert"];    }

}


简单罗列了一下,但具体思路应该大家都能看懂了,如有不明白的,请留言