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

你可能感兴趣的:(push)