菜鸟教程小白 发表于 2022-12-13 06:13:34

ios - 如何在 RPGLE 中构建 APNS 通知?


                                            <p><p>下午好,</p>

<p>我正在尝试创建一个连接到 Apple 推送通知服务 (APNS) 并发送推送通知的套接字程序。 </p>

<p>我想知道是否有人可以帮助我实际编写 APNS 通知。</p>

<p>您可以在下面看到我使用 Scott Klement 的套接字编程教程帮助我完成的程序。</p>

<p>可能与所有这些相关的代码在注释中标记为“APNS 通知格式开始”、“初始化”和“向 APNS 发送消息”,尽管我包含了整个程序以供引用。 </p>

<p>我已阅读 Apple 网站 <a href="https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/CommunicatingWIthAPS.html" rel="noreferrer noopener nofollow">Provider Requirements</a> 上的提供商要求但我仍然无法让一切正常工作。 </p>

<p>我的程序编译,当我调试它/运行我通过建立实际连接的步骤时,我“认为”这部分没问题。 </p>

<p>我希望在 item3 数据结构中的变量 errid 中从 Apple 取回错误标识符。 Apple 在提供者要求中声明,如果出现错误,他们会返回状态代码,但该特定变量仍为 1077952576</p>

<p>还有很多我不确定的事情</p>

<p>1) 我已获得作为 Base64 字符串的设备 token 。该字符串长度为 40 个奇数字符,但据我了解,Apple 声明设备 token 长度应为 32 个字节。在 RPGLE 中,1 个字符不是代表 1 个字节吗?如果是这种情况,那么我不能只将我的变量 token 声明为</p>

<pre><code>D   token                     32a
</code></pre>

<p>因为它会被切断?</p>

<p>2) 当我在变量 errid 中从 Apple 接收到正确的错误标识符时,有没有人能告诉我我做错了什么? </p>

<p>任何帮助将不胜感激</p>

<pre><code>H DFTACTGRP(*NO) BNDDIR(&#39;QC2LE&#39;)
D/copy socket_h
D/copy gskssl_h

*==============================================================*
*APNS Notification Format Begin                              
*==============================================================*
D request         s         1000a   varying

D framehdr      ds                        
D   command                      3I 0 inz(2)
D   framelen                  10I 0      

D framedta      s            500a   varying         

D item1         ds                                 
D   itemid1                      3I 0 inz(1)         
D   itemlen1                     5I 0 inz(%size(token))
D   token                     64a   

D item2         ds                                 
D   itemid2                      3I 0 inz(2)         
D   itemlen2                     5I 0                  
D   payload                  100a   varying         

D item3         ds                                 
D   itemid3                      3I 0 inz(3)         
D   itemlen3                     5I 0 inz(%size(errid))
D   errid                     10I 0

D item4         ds                                    
D   itemid4                      3I 0 inz(4)            
D   itemlen4                     5I 0 inz(%size(expire))
D   expire                      10I 0 inz(0)            

D item5         ds                                    
D   itemid5                      3I 0 inz(5)            
D   itemlen5                     5I 0 inz(%size(priority))
D   priority                  10I 0 inz(10)   

*==============================================================*
*APNS Notification Format End                                 
*==============================================================*         

D gsk_strerror    PR            *   extproc(&#39;gsk_strerror&#39;)
Dgsk_ret_value                10I 0 value                  

D CreateEnv       PR                  like(gsk_handle)      

D ConnSock      PR            10I 0                        
d   host                     256A   const                  
D   port                        10I 0 value                  

D UpgradeSock   PR                  like(gsk_handle)      
D    SslEnv                           like(gsk_handle) value
D    sock                     10I 0 value         

D CloseSsl      PR                                       
D    Handle                           like(gsk_handle) value

D CloseSslEnv   PR                                       
D    SslEnv                           like(gsk_handle) value

D ReportError   PR                                    

D EscapeMsg       PR         

D errMsg          s             80A   varying            
D CRLF            c                   x&#39;0d25&#39;            
D env             s                   like(gsk_handle)   
D s               s             10I 0                  
D connto          ds                  likeds(sockaddr_in)
D SslSock         s                   like(gsk_handle)   
D cmd             s            400A
D len             s             10I 0
D bytesSent       s             10I 0
D Reply         s         1000A
D bytesRead       s             10I 0
D left            s             10I 0
D buf             s               *
D received      s             10I 0
D dataPos         s             10I 0
D wait            s            1A
D rc            s             10I 0

/free                     

// Initialize
token = &#39;MyDevToken&#39;;
payload = &#39;{&#34;aps&#34;:{&#34;alert&#34;:&#34;You have mail&#34;}}&#39;;         
itemlen1 = %len(payload);                              
framedta = item1 + item2 + item3 + item4 + item5;      
framelen = %len(framedta);                           

request = framehdr + framedta;                        

// Create SSL Environment

env = CreateEnv();      
If (env = *NULL);      
   EscapeMsg();         
Endif;               

// Connect a socket to an SSL server (using normal socket calls)
// NOTE: Sandbox is the development environment               

s = ConnSock(&#39;gateway.sandbox.push.apple.com&#39;: 2195);      

// Upgrade the socket to SSL                                    

SSLSock = UpgradeSock(env: s);                                 
If (SSLSock = *NULL);   
   EscapeMsg();
Endif;                                                   

// **** Formulate message to APNS ******
len = %len(%trimr(request));

callp gsk_secure_soc_write(SSLSock
                        : %addr(request)
                        : len
                        : bytesSent);



// Close everything and end the program

CloseSsl(SslSock);                  
CloseSslEnv(Env);                  

*inlr = *on;                           

/end-free      


*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CreateEnv(): Create an SSL environment for client sockets
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CreateEnv       B                                          
D CreateEnv       PI                  like(gsk_handle)      
D rc            s             10I 0                        
D SslEnv          s                   like(Gsk_handle)      

/free                                                      

// Create an SSL environment with default values:         

rc = gsk_environment_open(SslEnv);                        
If (rc &lt;&gt; GSK_OK);                                       
errMsg = %str(gsk_strerror(rc));                        
return *NULL;                                          
Endif;                                                   

// Instruct environment to use the *SYSTEM certificate store

rc = gsk_attribute_set_buffer( SslEnv                     
                           : GSK_OS400_APPLICATION_ID   
                           : &#39;SUMITOMO_APNS_PUSH&#39;      
                           :0 );
If (rc&lt;&gt;GSK_OK);
   errMsg = %str(gsk_strerror(rc));
   gsk_environment_close( SslEnv );
   return *NULL;
Endif;

//Tell the environment that this is a client connection
rc = gsk_attribute_set_enum( SslEnv
   : GSK_SESSION_TYPE   
   : GSK_CLIENT_SESSION );

If (rc &lt;&gt; GSK_OK);               
   errMsg = %str(gsk_strerror(rc));
   gsk_environment_close( SslEnv );
   return *NULL;                  
Endif;                           

// Activate the new environment   

rc = gsk_environment_init( SslEnv );
If (rc &lt;&gt; GSK_OK);                  
   errMsg = %str(gsk_strerror(rc));
   gsk_environment_close( SslEnv );
   return *NULL;                  
Endif;

return SslEnv;

/end-free
P            E            

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* ConnSock(): Create a TCP Socket and connect to a host   
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P ConnSock      B                                          
D ConnSock      PI            10I 0                        
d   host                     256A   const                  
D   port                        10I 0 value                  
D s               s             10I 0                        
D addr            s             10U 0                        

/free                                                         

// look up host                           

addr = inet_addr(%trim(host));            
If (addr = INADDR_NONE);                  
   p_hostent = gethostbyname(%trim(host));
If (p_hostent = *NULL);               
   errMsg = &#39;Host not found!&#39;;         
   EscapeMsg();                        
Endif;                                 
   addr = h_addr;                        
Endif;

// Create a socket                           

s = socket(AF_INET: SOCK_STREAM: IPPROTO_IP);
If (s &lt; 0);                              
   ReportError();                        
Endif;

// connect to the host                              

connto = *ALLx&#39;00&#39;;                              
connto.sin_family = AF_INET;                     
connto.sin_addr   = addr;                        
connto.sin_port   = port;                        

If (connect(s: %addr(Connto): %size(connto)) = -1);
callp close(S);                                 
ReportError();                                 
Endif;                                             

return s;
/end-free
P             E

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* UpgradeSock():Upgrade a socket to use SSL               
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P UpgradeSock   B                                          
D UpgradeSock   PI                  like(gsk_handle)      
D    SslEnv                           like(gsk_handle) value
D    sock                     10I 0 value                  
D Handle          s                   like(Gsk_handle)      

/free   

rc = gsk_secure_soc_open(SslEnv: Handle);   
If (rc &lt;&gt; GSK_OK);               
   errMsg = %str(gsk_strerror(rc));
   return *NULL;                  
Endif;

rc = gsk_attribute_set_numeric_value(Handle
   : GSK_HANDSHAKE_TIMEOUT
   : 30 );

If (rc &lt;&gt; GSK_OK);               
   errMsg = %str(gsk_strerror(rc));
   gsk_secure_soc_close(Handle);   
   return *NULL;   
Endif;

rc = gsk_secure_soc_init( Handle );
If (rc &lt;&gt; GSK_OK);               
   errMsg = %str(gsk_strerror(rc));
   gsk_secure_soc_close(Handle);   
   return *NULL;                  
Endif;         

return Handle;
/end-free
P             E

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CloseSsl():Close an SSL socket                        
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CloseSsl      B                                          
D CloseSsl      PI                                       
D    Handle                           like(gsk_handle) value
/free                                                      
   gsk_secure_Soc_close( handle);                        
/end-free                                                   
P               E   

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* CloseSslEnv():Close SSL Environment                     
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P CloseSslEnv   B                                          
D CloseSslEnv   PI                                       
D    SslEnv                           like(gsk_handle) value
/free                                                      
   gsk_environment_close( SslEnv );                     
/end-free
P   E         

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* EscapeMsg(): Send an escape message w/reason for SSL failure      
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P EscapeMsg       B                                                
D EscapeMsg       PI                                                
D SndPgmMsg       PR                  ExtPgm(&#39;QMHSNDPM&#39;)            
D   MessageID                  7A   Const                        
D   QualMsgF                  20A   Const                        
D   MsgData                  256A   Const                        
D   MsgDtaLen                   10I 0 Const                        
D   MsgType                     10A   Const                        
D   CallStkEnt                  10A   Const                        
D   CallStkCnt                  10I 0 Const                        
D   MessageKey                   4A                                 
D   ErrorCode                  1A      

D ErrorCode       DS                        
DBytesProv                  10I 0 inz(0)
DBytesAvail                   10I 0 inz(0)

D wwTheKey      S            4A

/free
SndPgmMsg( &#39;CPF9897&#39;
: &#39;QCPFMSG   *LIBL&#39;   
: errMsg            
: %len(%trimr(errMsg))
: &#39;*ESCAPE&#39;         
: &#39;*CTLBDY&#39;         
: 1                  
: wwTheKey            
: ErrorCode );
/end-free
P          E

*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
* ReportError():Send an escape message explaining any errors   
*               that occurred.                                 
*                                                               
*This function requires binding directory QC2LE in order      
*to access the __errno() function.                              
*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
P ReportError   B                                                
D ReportError   PI                                             

D get_errno       PR            *   ExtProc(&#39;__errno&#39;)         
D ptrToErrno      s               *                              
D errno         s             10I 0 based(ptrToErrno)      

D QMHSNDPM      PR                  ExtPgm(&#39;QMHSNDPM&#39;)
D   MessageID                  7A   Const            
D   QualMsgF                  20A   Const            
D   MsgData                      1A   Const            
D   MsgDtaLen                   10I 0 Const            
D   MsgType                     10A   Const            
D   CallStkEnt                  10A   Const            
D   CallStkCnt                  10I 0 Const            
D   MessageKey                   4A                     
D   ErrorCode               8192A   options(*varsize)

D ErrorCode       DS                  qualified
DBytesProv            1      4I 0 inz(0)   
DBytesAvail             5      8I 0 inz(0)   

D MsgKey          S            4A
D MsgID         s            7A

/free

ptrToErrno = get_errno();   
MsgID = &#39;CPE&#39; + %char(errno);

QMHSNDPM( MsgID
: &#39;QCPFMSG   *LIBL&#39;
: &#39; &#39;            
: 0               
: &#39;*ESCAPE&#39;      
: &#39;*PGMBDY&#39;      
: 1   
: MsgKey            
: ErrorCode         );         
/end-free
P          E
</code></pre></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>这还不够接近,您使用的是字符而不是二进制数据。</p>

<pre><code>cmd = &#39;2&#39; + 3 + 1 + 64 + &#39;x&#39; + 2 + 50 + &#39;{&#34;aps&#34;:{&#34;alert&#34;:&#34;You have mail&#34;}} +
      3 + 3 + &#39;001&#39;
</code></pre>

<p>这应该更接近;但它不在我的脑海中,完全未经测试...... </p>

<pre><code> d request         s         1000a   varying

d frame_hdr       ds
dcmd                           1a   inz(x&#39;02&#39;)
dframe_len                  10i 0

d frame_data      s            500a   varying

d device_item   ds
d                              1a   inz(x&#39;01&#39;)
d                              5i 0 inz(%size(device_item))
dtoken                        32a

d item_hdr      ds
did                            1a   inz(x&#39;02&#39;)
ditem_len                      5i 0


d item_data       s            100a   varying

   item_data = &#39;{&#34;aps&#34;:{&#34;alert&#34;:&#34;You have mail&#34;}}&#39;;
   item_len = %len(item_data);

   token = myDevID;
   frame_data = device_item + item_hdr + item_data;
   frame_len = %len(frame_data);

   request = frame_hdr + frame_data;

   callp gsk_secure_soc_write(SSLSock
                      : %addr(request:*DATA)
                      : %len(request)
                      : bytesSent);
</code></pre>

<p>我以前没有在 IBM i 上做过原始套接字,您可能需要将 EBCDIC 转换为 ASCII。我认为您无需担心小端与大端。 </p>

<p>RPG 可能不是最好的选择,考虑到 <a href="https://code.google.com/p/javapns/" rel="noreferrer noopener nofollow">Java PNS</a> 等项目的存在,Java 可能是更好的选择。 </p>

<p>Stackoverflow 没有大量的 RPG/IBM i 流量。您可能会在以下方面得到更好的回应:</p>

<ul>
<li> <a href="http://lists.midrange.com/mailman/listinfo/rpg400-l" rel="noreferrer noopener nofollow">http://lists.midrange.com/mailman/listinfo/rpg400-l</a> </li>
<li> <a href="http://lists.midrange.com/mailman/listinfo/web400" rel="noreferrer noopener nofollow">http://lists.midrange.com/mailman/listinfo/web400</a> </li>
<li> <a href="http://www.scottklement.com/mailman/listinfo/ftpapi" rel="noreferrer noopener nofollow">http://www.scottklement.com/mailman/listinfo/ftpapi</a> </li>
</ul></p>
                                   
                                                <p style="font-size: 20px;">关于ios - 如何在 RPGLE 中构建 APNS 通知?,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/29401333/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/29401333/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: ios - 如何在 RPGLE 中构建 APNS 通知?