总结较好的文档:http://www.ityran.com/archives/240

/*
 
若1秒内对同一个用户产生大量的推送请求,会造成该用户接收正常速度的消息时前总是收到之前已经推送过的消息,这所谓重复消息。 经过测试发现,即便provider产生大量推送请求,apns推送给iPhone的时间间隔大约为3s。那么应该在provider端设计一种算法,使得 对同一个用户大量并发的请求以3秒间隔地推送。实践结果,果然。


*/


#pragma pack(1)
struct STRU_PUSHDATA
{
public:
     void setFieldCommand(uint8 auCommand)
    {
        muCommand = auCommand;
    }
     void setFieldIdentifier(uint32  auIdentifier)
    {
        muIdentifier = auIdentifier;
    }
     void setFieldExpiry(uint32  auExpiry)
    {
        muExpiry = htonl(auExpiry);    
    }
     void setFieldTokenLen(uint16  auTokenLen)
    {
        muTokenLen = htons(auTokenLen);    
    }
     void setFieldToken( const uint8* apToken)
    {
        memcpy(mszToken,apToken,32);
    }
     void setFieldPayloadLen(uint16  auPayloadLen)
    {
        muPayloadLen = htons(auPayloadLen);
    }
     void setFieldPayLoad( const  char* apszPayload,uint16 auPayloadLen)
    {
        memcpy(mszPayload,apszPayload,auPayloadLen);
    }

    inline  const uint8* getPushDataAddr()  const
    {
         return (uint8*)&muCommand;
    }

    inline  uint16 getPushDataLen() 
    {
         return (1+4+4+2+32+2+getPayloadLen());
    }

    inline uint16 getPayloadLen()
    {
         return ntohs(muPayloadLen);
    }

    std:: string getPayloadString()
    {
         int nLen = getPayloadLen();
         if (nLen>=256)
        {
             return std:: string("");
        }
        mszPayload[nLen]='\0';
         return std:: string(mszPayload);
    }

    inline  void setFieldFromId( const uint64& auFromId)
    {
        muFromId = auFromId;
    }
    inline  void setFieldToId( const uint64& auToId)
    {
        muToId = auToId;
    }
    inline  const uint64& getFieldFromId() const
    {
         return muFromId;
    }
    inline  const uint64& getFieldToId()  const
    {
         return muToId;
    }    


    STRU_PUSHDATA()
    {
        init();
    }

     void init()
    {
        memset( this,0, sizeof(* this));
    }

    uint8   muCommand;
    uint32  muIdentifier;
    uint32  muExpiry;
    uint16  muTokenLen;
    uint8    mszToken[32];
    uint16  muPayloadLen;
     char    mszPayload[256+1];
    uint16  iPayloaLlen;
    uint64  muFromId;
    uint64  muToId;
    STRU_PUSHDATA* next; // *指向下一个STRU_PUSHDATA
};
#pragma pack(0)




//  类名:CApnsAdapter
//  功能:与apns交互的适配器,适配器时一个包含各种推送策略的推送发射装置
//  设计者:zhangtao 20140419
typedef  void (*PFCALLBACK_EVENT_ON_TRAVERSAL)(HANDLE ahCallBack,STRU_PUSHDATA* apData);
typedef  void (*PFCALLBACK_EVENT_ON_CLEARCACHE)(HANDLE ahCallBack,STRU_PUSHDATA* apData);
class CApnsAdapter
{
public:
     struct HEAD_NODE
    {
        uint64         muToId;
        uint32         muLastPushTime;
        STRU_PUSHDATA* mpHead;
        STRU_PUSHDATA* mpTail;    
        uint32         muCount;
        HEAD_NODE():muToId(0),muLastPushTime(0),mpHead(NULL),mpTail(NULL),muCount(0)
        {
             // *构造
        }
        HEAD_NODE(uint64 auId,uint32 auTime):muToId(auId),muLastPushTime(auTime),mpHead(NULL),mpTail(NULL),muCount(0)
        {
             // *构造
        }
         bool  operator==( const HEAD_NODE& rhs)  const
        {
             return (muToId == rhs.muToId);
        }
         void push_back(STRU_PUSHDATA* mpData)
        {
             if(NULL == mpHead)
            {
                mpHead = mpData;                
            }
             else
            {
                mpTail->next = mpData;
            }
            mpData->next = NULL;
            mpTail = mpData;
            muCount++;
        }
        STRU_PUSHDATA* pop_front()
        {
             if (NULL == mpHead || NULL ==mpTail)
            {
                 return NULL;
            }
            STRU_PUSHDATA* lpData = mpHead;
            mpHead = mpHead->next;
            muCount--;
             return lpData;
        }
        STRU_PUSHDATA* get_front()
        {
             if (NULL == mpHead || NULL ==mpTail)
            {
                 return NULL;
            }
             return mpHead;
        }
         bool is_empty()
        {
             return ( NULL == mpHead) ;
        }
        uint16 get_count()
        {
            
             return muCount;
        }
         void set_lastpushtime( const uint32& auCurTime)
        {
            muLastPushTime = auCurTime;
        }
         bool is_canpush( const uint32& auCurTime)
        {
             return  (auCurTime >= muLastPushTime+3); // 3是实践出来的值
        }
    };
    CApnsAdapter():mhcbContext(NULL),mpcbEventOnTraversal(NULL),mpcbEventOnClearCache(NULL)
    {

    }
    ~CApnsAdapter()
    {
        clear_all_cache();
    }
     void setCallbackEvent(HANDLE ahcbContext,PFCALLBACK_EVENT_ON_TRAVERSAL  apcbEventOnTraversal,PFCALLBACK_EVENT_ON_CLEARCACHE apcbEventOnClearCache)
    {
        mhcbContext           = ahcbContext;
        mpcbEventOnTraversal  = apcbEventOnTraversal;
        mpcbEventOnClearCache = apcbEventOnClearCache;
    }
     bool is_empty()
    {
         return ( 0 == moNodeList.size());
    }
    uint16 size()
    {
         return moNodeList.size();
    }

     // *先缓冲待推送的数据请求,然后又策略地推送
     void add_data_to_cache( STRU_PUSHDATA* mpData)
    {
        HEAD_NODE node(mpData->getFieldToId(),0);
        std::list<HEAD_NODE>::iterator it = std::find(moNodeList.begin(),moNodeList.end(),node);
         if (it != moNodeList.end())
        {
            it->push_back(mpData);
        } 
         else
        {
            node.push_back(mpData);
            moNodeList.push_back(node);
        }
    }
     void active_push_on_traversal()
    {
        uint32 uNowTime = (uint32)time(NULL);
        std::list<HEAD_NODE>::iterator it = moNodeList.begin();
         for ( ; it != moNodeList.end() ;)
        {
        
             if ( it->is_canpush( uNowTime ))
            {
                 if ( it->is_empty() )
                {
                    moNodeList.erase( it++ );
                     continue;
                } 
                 else
                {
                    STRU_PUSHDATA * lpData = it->pop_front()
                     if ( NULL != mpcbEventOnTraversal)
                    {
                        mpcbEventOnTraversal(mhcbContext,lpData);
                    }
                    it->set_lastpushtime( uNowTime );
                }
            }
             else
            {
            
            }
            
            it++;            
        }
    }
     void clear_all_cache()
    {
        std::list<HEAD_NODE>::iterator it = moNodeList.begin();
         for ( ; it != moNodeList.end() ;)
        {
             if ( it->is_empty() )
            {
                moNodeList.erase( it++ );
                 continue;
            } 
             else
            {
                STRU_PUSHDATA* lpPushData = NULL;
                 while( NULL != (lpPushData = it->pop_front()) )
                {
                     if ( NULL != mpcbEventOnClearCache)
                    {
                        mpcbEventOnClearCache(mhcbContext,lpPushData);
                    }
                }

                it++;
            }
        }

        moNodeList.clear();
    }

     void print_each_node();

private:
    std::list<HEAD_NODE>           moNodeList;
    HANDLE                           mhcbContext;
    PFCALLBACK_EVENT_ON_TRAVERSAL  mpcbEventOnTraversal;
    PFCALLBACK_EVENT_ON_CLEARCACHE mpcbEventOnClearCache;
};