注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

眼睛想旅行

技术就是我的生命与信仰!

 
 
 

日志

 
 
关于我

精通C,C++,python,Erlang。并熟悉各种其他编程语言,用cocos2dx游戏引擎作过几个项目。会MySQL增删改查,了解OpenGL渲染原理。懂单片机,能设计数字电路系统,会画电路图和设计电路板。喜欢了解最新前沿技术,并持续关注和学习新技术。

网易考拉推荐

iOS推送  

2015-08-01 00:13:36|  分类: ios学习 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

http://www.cocoachina.com/industry/20130321/5862.html

原文太常了,就不转了。可以去原文看。写的很全面。

ios8中的推送,看下文

http://blog.csdn.net/apple_app/article/details/39228221

上边的文章讲的是使用php的,下边这个是使用pyhton的一个第三方库实现的。

另一个python推送,applepush:http://python.jobbole.com/86847/

pip install applepush

http://www.tuicool.com/articles/aqYBna

pip install pyapns

或者使用

easy_install pyapns

如果上边两个下载twistd有问题,可以从下边的地址下载twistd

https://pypi.python.org/packages/18/85/eb7af503356e933061bf1220033c3a85bad0dbc5035dfd9a97f1e900dfcb/Twisted-16.2.0.tar.bz2

或者直接在服务器终端里输入:

curl -O https://pypi.python.org/packages/18/85/eb7af503356e933061bf1220033c3a85bad0dbc5035dfd9a97f1e900dfcb/Twisted-16.2.0.tar.bz2

下载好之后,使用

tar -xvjf Twisted-16.2.0.tar.bz2

解压后,进入目录,使用sudo python setup.py install安装

启动twisted

#linux
twistd -r epoll web --class=pyapns.server.APNSServer --port=7077

#mac os
twistd -r kqueue web --class=pyapns.server.APNSServer --port=7077

我在运行这个的时候出了些问题,在mac上运行时发现少了一个叫libffi的库,要安装上这个才能运行。安装之后一,又少service-identity,再后来说openssl的库找不到.使用下边方法

sudo ln -s /Users/username/anaconda/lib/libssl.1.0.0.dylib  /usr/lib/libssl.1.0.0.dylib

sudo ln -s  /Users/username/anaconda/lib/libcrypto.1.0.0.dylib  /usr/lib/libcrypto.1.0.0.dylib

在ubuntu linux上发现用pip安装的twistd没有web的这个命令,后来使用

sudo apt-get install python-twisted python-libxml2 python-simplejson

使用上边的命令安装好了twistd之后运行web命令又说少了service-identity,使用pip install service-identity进行安装时又说pyopenssl的版本不对。

再使用sudo pip install openssl进行openssl安装,接着运行twistd,发现已经有一个进程在运行了。这时找到twistd进程,使用。

kill pid

终止进程后,再运行

#linux
twistd -r epoll web --class=pyapns.server.APNSServer --port=7077

#mac os
twistd -r kqueue web --class=pyapns.server.APNSServer --port=7077

没有报错,这时就可以新建下边的push.py文件了,如果运气好,你的手机应该会收到推送消息。但是也有可能你在生成pem文件时使用了密码。而pyapns默认是不使用密码的。这个时候用下边的方法重新生成一个没有安装密码的ck.pem文件。

openssl rsa -in PushChatKey.pem -out PushChatKey-noenc.pem。
cat PushChatCert.pem PushChatKey-noenc.pem > ck.pem

新建push.py文件输入下面内容

#!/usr/bin/python
# -*- coding: utf-8 -*
# Filename: push.py

from pyapns import configure, provision, notify

tokens = ["token1" ,
          "token2"]

notifications = [
    {'aps' :{'alert': 'Hello token 1', 'badge': 0, 'sound': 'flynn.caf'}},
]

configure({'HOST': 'http://localhost:7077/'})
provision('myapp', open('developent.pem').read(), 'sandbox')
notify('myapp', tokens, notifications)

pyapns推送消息  需要一个pem格式的证书文件,跟 Parse 里要求一个.p12文件不同啊。我看看怎么搞到这文件。从苹果下载的证书是.cer格式的,在苹果的KeyChain程序中,选择导出,可是,只能选择导出成.cer和.p12文件,.pem的选项被禁用了,好桑心。通过搜索export pem from keychain找到 Creating .pem file for APNS? ,简单说,就是在KeyChain里导出.p12格式的,再通过下面的命令转换成.pem的。搞定。

openssl pkcs12 -in Development.p12 -out developent.pem -nodes -clcerts

python push.py

推送成功

完成

pyapns源码:

https://github.com/samuraisam/pyapns

具体的.pem文件生成:

处理证书

打开终端.

cd到桌面,我们那三个文件所在的位置

三个文件:

一个是CSR请求文件,一个是aps_development .cer的SSL证书文件,还有一个刚才生成的Push.p12秘钥文件


1、把.cer的SSL证书转换为.pem文件,执行命令:

openssl x509 -in aps_development.cer -inform der -out PushChatCert.pem


在桌面上会生成一个PushChatCert.pem文件

localhost:Desktop oukoumine$ openssl x509 -in ps_development.cer -inform der -out PushChatCert.pem

localhost:Desktop oukoumine$

2、把私钥Push.p12文件转化为.pem文件:

openssl pkcs12 -nocerts -out PushChatKey.pem -in Push.p12

这里需要我们输入密码,这个密码也就是我们导出p12文件时的密码,也就是我们上面设置的abcabc。然后,需要我们对生成的pem文件设置一个密语,这里我们推荐还是用上面这个abcabc,防止混乱(当然你也可以设置成别的更有意义的密语),这里的密语是要告诉我们服务器的。这样,桌面上又会生成一个PushChatKey.pem文件


 

3、对生成的这两个pem文件再生成一个pem文件,来把证书和私钥整合到一个文件里:

cat PushChatCert.pem PushChatKey.pem > ck.pem
生成ck.pem文件


这样,我们的文件就制作完了

项目测试

建立我们的推送的项目(注意BundleIdentifier必须和我们推送应用的App id一致

在AppDelegate里didFinishLaunchingWithOptions函数里写

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

{

……

  //推送的形式:标记,声音,提示


   [[UIApplication sharedApplication] registerForRemoteNotificationTypes: UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert];

//上边的方法在ios8以上的版本不能用了。ios8以后要使用新的方法

iOS推送 - ♂苹果 - 眼睛想旅行

 

   return YES;

}

 

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)pToken {

   NSLog(@"regisger success:%@",pToken);

   //注册成功,将deviceToken保存到应用服务器数据库中

}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{

    // 处理推送消息

    NSLog(@"userinfo:%@",userInfo);

   

    NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);

}

- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {

   NSLog(@"Registfail%@",error);

}

我们运行程序的时候会有提示,说我们的程序要发送推送通知。


C++推送服务器端:

转自:http://www.cocoachina.com/bbs/read.php?tid=74676

SSLCOMM_H文件

#ifndef SSLCOMM_H

#define SSLCOMM_H

 

#ifdef linux

#include <assert.h>

#include "openssl/pem.h"

#include "openssl/rsa.h"

#include "openssl/crypto.h"

#include "openssl/x509.h"

#include "openssl/ssl.h"

#include "openssl/err.h"

#include "openssl/rand.h"

 

#include "errno.h"

#include "sys/socket.h"

#include "netinet/in.h"

#include "unistd.h"

#include <arpa/inet.h>

#include <netdb.h>

 

#include "Utility.h"

 

#define APNS_DEV

#if defined(APNS_DEV)

 

#define CA_CERT_PATH    "./pem"

#define RSA_CLIENT_CERT     "./pem/a.pem"

#define RSA_CLIENT_KEY      "./pem/a.pem"

/* Development Connection Infos */

#define APPLE_HOST          "gateway.sandbox.push.apple.com"

#define APPLE_PORT          2195

 

#define APPLE_FEEDBACK_HOST "feedback.sandbox.push.apple.com"

#define APPLE_FEEDBACK_PORT 2196

 

#else

#define CA_CERT_PATH    "./pem"

#define RSA_CLIENT_CERT     "./pem/b.pem"

#define RSA_CLIENT_KEY      "./pem/b.pem"

#define APPLE_HOST          "gateway.push.apple.com"

#define APPLE_PORT          2195

#define APPLE_FEEDBACK_HOST "feedback.push.apple.com"

#define APPLE_FEEDBACK_PORT 2196

#endif

 

 

class CSSLComm

{

 public:

    CSSLComm();

    ~CSSLComm();

 

    bool connected();

    bool ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char* capath);

    void PushNotification(const char *pToken,const char *pMsg);

 

    void GenPushData(const char *pToken);

    int GenPayloadData(int badgeNum,const char *pMsg = NULL);

 

    private:

    void Reset();

 

    private:

 

    SSL_CTX         *m_pctx;

    SSL             *m_pssl;

    const SSL_METHOD      *m_pmeth;

    X509            *m_pserver_cert;

    EVP_PKEY        *m_pkey;

 

    /* Socket Communications */

    struct sockaddr_in   m_server_addr;

    struct hostent      *m_phost_info;

 

    int                  m_sockfd;

    uint16 m_tokenLen;

    struct PUSHDATA

    {

        char szToken[1+2+32];

        char szPayload[2+256];

    }m_data;

 

    CSyncCritical m_lock;

};

 

#endif

 

#endif // SSLCOMM_H


SSLComm.cpp

#ifdef linux

 

#include "SSLComm.h"

 

CSSLComm::CSSLComm()

{

    //ctor

    m_sockfd = -1;

    m_pctx = NULL;

    m_pssl = NULL;

    m_pmeth = NULL;

    m_pserver_cert = NULL;

    m_pkey = NULL;

 

    m_tokenLen = htons(32);

    memset((void*)&m_data,0,sizeof(m_data));

 

}

 

CSSLComm::~CSSLComm()

{

    //dtor

    Reset();

 

}

void CSSLComm::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;

    }

    if(m_sockfd > 2)

    {

        close(m_sockfd);

        m_sockfd = -1;

    }

 

}

 

 

bool CSSLComm::connected()

{

    if(m_sockfd < 2) return false;

 

    struct timeval timeout;

    timeout.tv_sec = 0;

    timeout.tv_usec = 0;

    fd_set fdwrite;

    fd_set fdexcept;

    FD_ZERO(&fdwrite);

    FD_ZERO(&fdexcept);

    FD_SET(m_sockfd,&fdwrite);

    FD_SET(m_sockfd,&fdexcept);

    int ret = select(m_sockfd+1,NULL,&fdwrite,&fdexcept,&timeout);

    if(ret == -1)

        return false;

    if(ret > 0)

    {

        if(FD_ISSET(m_sockfd,&fdexcept))

            return false;

        else if(FD_ISSET(m_sockfd,&fdwrite))

        {

            int err = 0;

            socklen_t len = sizeof(err);

            int result = getsockopt(m_sockfd,SOL_SOCKET,SO_ERROR,(char*)&err,&len);

            if(result < 0 || err != 0)

                return false;

            return true;

        }

    }

    return false;

}

 

 

bool CSSLComm::ssl_connect(const char *host, int port, const char *certfile, const char *keyfile, const char* capath)

{

    Reset();

 

    int err;

 

    /* Load encryption & hashing algorithms for the SSL program */

    SSL_library_init();

 

    /* Load the error strings for SSL & CRYPTO APIs */

    SSL_load_error_strings();

 

    /* Create an SSL_METHOD structure (choose an SSL/TLS protocol version) */

    m_pmeth = SSLv3_method();

 

    /* Create an SSL_CTX structure */

    m_pctx = SSL_CTX_new(m_pmeth);

    if(!m_pctx)

    {

        printf("Could not get SSL Context\n");

        return false;

    }

 

    /* Load the CA from the Path */

    if(SSL_CTX_load_verify_locations(m_pctx, NULL, capath) <= 0)

    {

        /* Handle failed load here */

        printf("Failed to set CA location...\n");

        ERR_print_errors_fp(stderr);

        return false;

    }

 

    /* Load the client certificate into the SSL_CTX structure */

    if (SSL_CTX_use_certificate_file(m_pctx, certfile, SSL_FILETYPE_PEM) <= 0)

    {

        printf("Cannot use Certificate File\n");

        ERR_print_errors_fp(stderr);

        return false;

    }

 

    /* Load the private-key corresponding to the client certificate */

    if (SSL_CTX_use_PrivateKey_file(m_pctx, keyfile, SSL_FILETYPE_PEM) <= 0)

    {

        printf("Cannot use Private Key\n");

        ERR_print_errors_fp(stderr);

        return false;

    }

 

    /* Check if the client certificate and private-key matches */

    if (!SSL_CTX_check_private_key(m_pctx))

    {

        printf("Private key does not match the certificate public key\n");

        return false;

    }

 

    /* Set up a TCP socket */

    m_sockfd = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);

    if(m_sockfd == -1)

    {

        printf("Could not get Socket\n");

        return false;

    }

 

    memset (&m_server_addr, '\0', sizeof(m_server_addr));

    m_server_addr.sin_family      = AF_INET;

    m_server_addr.sin_port        = htons(port);       /* Server Port number */

    m_phost_info = gethostbyname(host);

    if(m_phost_info)

    {

        /* Take the first IP */

        struct in_addr *address = (struct in_addr*)m_phost_info->h_addr_list[0];

        m_server_addr.sin_addr.s_addr = inet_addr(inet_ntoa(*address)); /* Server IP */

 

    }

    else

    {

        printf("Could not resolve hostname %s\n", host);

        return false;

    }

 

    /* Establish a TCP/IP connection to the SSL client */

    err = connect(m_sockfd, (struct sockaddr*) &m_server_addr, sizeof(m_server_addr));

    if(err == -1)

    {

        printf("Could not connect\n");

        return false;

    }

 

    /* An SSL structure is created */

    m_pssl = SSL_new(m_pctx);

    if(!m_pssl)

    {

        printf("Could not get SSL Socket\n");

        return false;

    }

 

    /* Assign the socket into the SSL structure (SSL and socket without BIO) */

    SSL_set_fd(m_pssl, m_sockfd);

 

    /* Perform SSL Handshake on the SSL client */

    err = SSL_connect(m_pssl);

    if(err == -1)

    {

        printf("Could not connect to SSL Server\n");

        return false;

    }

    return true;

 

}

 

void CSSLComm::PushNotification(const char *pToken,const char *pMsg)

{

    CMyLock lock(&m_lock);

    if(!connected())

    {

        ssl_connect(APPLE_HOST, APPLE_PORT, RSA_CLIENT_CERT, RSA_CLIENT_KEY, CA_CERT_PATH);

    }

    int paylen = GenPayloadData(1,pMsg);

    GenPushData(pToken);

    int ret = SSL_write(m_pssl, (void*)&m_data, 35 + paylen);

    //printf("ret = %d \n",ret);

}

 

void CSSLComm::GenPushData(const char *pToken)

{

    char *ptr = m_data.szToken;

    *ptr++ = 0;

    memcpy(ptr,&m_tokenLen,2);

    ptr += 2;

    memcpy(ptr,pToken,32);

}

 

int CSSLComm::GenPayloadData(int badgeNum,const char *pMsg)

{

    char buf[256] = {0};

    char badgeBuf[3] = {0};

    strcpy(&m_data.szPayload[2], "{\"aps\":{");

    if(pMsg != NULL)

    {

        strcat(&m_data.szPayload[2], "\"alert\":");

        snprintf(buf, sizeof(buf)-1,"\"%s\",", pMsg);

        strcat(&m_data.szPayload[2],buf);

    }

    if(badgeNum > 99 || badgeNum < 0) badgeNum = 1;

    snprintf(badgeBuf, sizeof(badgeBuf)-1,"%d", badgeNum);

    strcat(&m_data.szPayload[2], "\"badge\":");

    strcat(&m_data.szPayload[2], badgeBuf);

    strcat(&m_data.szPayload[2], ",\"sound\":\"msg.wav\"}");

    /*

        int i = 0;

        while(payload->dictKey<i> != NULL && i < 5)

        {

            sprintf(tmpBuff, "\"%s\":\"%s\"", payload->dictKey<i>, payload->dictValue<i>);

            strcat(messageBuff, tmpBuff);

            if(i < 4 && payload->dictKey[i + 1] != NULL)

            {

                strcat(messageBuff, ",");

            }

            i++;

        }

    */

 

    snprintf(buf, sizeof(buf)-1,",\"%s\":\"%d\"", "forum_id",88);

    strcat(&m_data.szPayload[2],buf);

 

    snprintf(buf, sizeof(buf)-1,",\"%s\":\"%d\"", "topic_id",999);

    strcat(&m_data.szPayload[2],buf);

 

    strcat(&m_data.szPayload[2],"}");

    int len = strlen(&m_data.szPayload[2]);

    assert(len <= 256);

    uint16_t payload_len = htons(len);

    memcpy(m_data.szPayload,&payload_len,sizeof(payload_len));

    return len + 2;

}

 

#endif

另外还有一些第三方的推送平台,用第三方平台的好处就是操作简单,不同系统的设备推送接口统一。缺点只有一个,就是推送数据的全安性,以及到一定量时要收费。Python新版本升级方法:
Linux系统登陆密码忘了怎么办:
使用系统安装盘,进入修复模式,输入
 passwd <用户名>
就可以输入新密码了。我是在ubuntu 14.04上试的。
  评论这张
 
阅读(257)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017