• IOS 的 PUSH 封装


    服务器端的主要工作是:从客户端获取到deviceToken,随同需要发送的内容,按IOS规定格式打包发送。

    1.先获得证书(从客户端开发人员要来的)Certificates.p12 通过输入命令生成 PEM 格式

    openssl pkcs12 -clcerts -nokeys -out cert.pem -in aps_development.p12
    //会要求提供密码,密码为空,直接回车即可    
    openssl pkcs12 -nocerts -out key.pem -in aps_development.p12 
    //会要求设置密码和确认设置密码。这里我们用是的是123456    
    openssl rsa -in key.pem -out key.unencrypted.pem     
    //会要求输入之前设置的密码
    cat cert.pem key.unencrypted.pem > iostest_push_dev.pem

    2. deviceToken 是一个字符串。形如:<304eb5c5 5b8a36ba a072a5ff b6e9ada9 9d5a1b8c 89f9f1c1 ac8cc3dd fe9a86fd>

    注意:ios要求token的格式是binary,所以发送前需要转换下,且要跳过 空格 和 "<", ">"

    3、代码实现:

    #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 <arpa/inet.h>
    #include <string>
    using namespace std;
    // 证书文件
    #define CERTFILE "cert/aps_developer_identity.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(string _token, string _payload)
    {
     const char *token = _token.c_str();
     string payloadstr =  "{\"aps\":{\"alert\":\"";
     payloadstr += string(_payload);
     payloadstr +=  "\"}}";
     cout<<"pushStr: "<< payloadstr;
     const char *payload = payloadstr.c_str();
     char host[] = "gateway.sandbox.push.apple.com:2195";
     BIO *conn;
     // init
     SSL_library_init();
     ctx = setup_client_ctx();
     conn = BIO_new_connect(host);
     if (!conn) {
      error("Error creating connection BIO\n");
      return -1;
     }
     if (BIO_do_connect(conn) <= 0) {
      error("Error connection to remote machine");
      return -1;
     }
     if (!(ssl = SSL_new(ctx))) {
      error("Error creating an SSL contexxt");
      return -1;
     }
     SSL_set_bio(ssl, conn, conn);
     if (SSL_connect(ssl) <= 0) {
      error("Error connecting SSL object");
      return -1;
     }
     printf("SSL Connection opened\n");
     char tokenBytes[32];
     char message[293];
     unsigned long msgLength;
     token2bytes(token, tokenBytes);
     msgLength = packMessage(message, 0, tokenBytes, payload);
     int reValue = SSL_write(ssl, message, (int)msgLength);
     SSL_shutdown(ssl);
     SSL_free(ssl);
     SSL_CTX_free(ctx);
     return reValue;
    }

    参考:http://blog.csdn.net/bingwen0210/article/details/6622238

  • 相关阅读:
    HDU1213How Many Tables并查集
    Redis新的存储模式diskstore
    GPFS文件系统笔记
    redis持久化
    360安全卫士qurl.f.360.cn分析
    [原创]解决DataSet的GetXml()方法空列不返回问题
    在多台服务器上简单实现Redis的数据主从复制
    史航416随笔
    史航416实验1总结
    史航416第二次作业总结
  • 原文地址:https://www.cnblogs.com/tianyajuanke/p/2523888.html
Copyright © 2020-2023  润新知