下午好,
我正在尝试创建一个套接字程序,它连接到Apple推送通知服务(APNS)并发送推送通知。
我想知道是否有人可以帮助我实际编写APNS通知。
下面你可以看到我使用Scott Klement的套接字编程教程来帮助我的程序。
可能与此相关的代码标记为' APNS通知格式开始'初始化'以及'向APNS制定消息'在评论中虽然我包括整个计划以供参考。
我已阅读Apple网站Provider Requirements上的提供商要求,但我仍然无法使所有内容正常运行。
我的程序编译,当我调试它/运行我已经过去建立一个实际连接的步骤,所以我认为'这部分还可以。
我希望在item3数据结构中的变量errid中从Apple获取错误标识符。 Apple在提供商要求中声明,如果出现错误,他们会返回状态代码,但该特定变量仍为1077952576
还有很多其他我不确定的事情
1)我已将设备令牌作为Base64字符串。字符串是40个奇怪的字符,但据我所知,Apple声明设备令牌长度应该是32个字节。在RPGLE中,1个字符代表1个字节吗?如果是这样,那么我就不能将我的变量标记声明为
D token 32a
因为它会被切断?
2)当我的变量errid中返回从Apple接收正确的错误标识符时,是否有人能够告诉我我做错了什么?
非常感谢任何帮助
H DFTACTGRP(*NO) BNDDIR('QC2LE')
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('gsk_strerror')
D gsk_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'0d25'
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 = 'MyDevToken';
payload = '{"aps":{"alert":"You have mail"}}';
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('gateway.sandbox.push.apple.com': 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 <> 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
: 'SUMITOMO_APNS_PUSH'
:0 );
If (rc<>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 <> 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 <> 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 = 'Host not found!';
EscapeMsg();
Endif;
addr = h_addr;
Endif;
// Create a socket
s = socket(AF_INET: SOCK_STREAM: IPPROTO_IP);
If (s < 0);
ReportError();
Endif;
// connect to the host
connto = *ALLx'00';
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 <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
return *NULL;
Endif;
rc = gsk_attribute_set_numeric_value(Handle
: GSK_HANDSHAKE_TIMEOUT
: 30 );
If (rc <> GSK_OK);
errMsg = %str(gsk_strerror(rc));
gsk_secure_soc_close(Handle);
return *NULL;
Endif;
rc = gsk_secure_soc_init( Handle );
If (rc <> 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('QMHSNDPM')
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
D BytesProv 10I 0 inz(0)
D BytesAvail 10I 0 inz(0)
D wwTheKey S 4A
/free
SndPgmMsg( 'CPF9897'
: 'QCPFMSG *LIBL'
: errMsg
: %len(%trimr(errMsg))
: '*ESCAPE'
: '*CTLBDY'
: 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('__errno')
D ptrToErrno s *
D errno s 10I 0 based(ptrToErrno)
D QMHSNDPM PR ExtPgm('QMHSNDPM')
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
D BytesProv 1 4I 0 inz(0)
D BytesAvail 5 8I 0 inz(0)
D MsgKey S 4A
D MsgID s 7A
/free
ptrToErrno = get_errno();
MsgID = 'CPE' + %char(errno);
QMHSNDPM( MsgID
: 'QCPFMSG *LIBL'
: ' '
: 0
: '*ESCAPE'
: '*PGMBDY'
: 1
: MsgKey
: ErrorCode );
/end-free
P E
答案 0 :(得分:1)
这甚至不接近,你使用的是字符而不是二进制数据。
cmd = '2' + 3 + 1 + 64 + 'x' + 2 + 50 + '{"aps":{"alert":"You have mail"}} +
3 + 3 + '001'
这应该更接近;但它完全脱离了我的头脑,完全没有经过考验......
d request s 1000a varying
d frame_hdr ds
d cmd 1a inz(x'02')
d frame_len 10i 0
d frame_data s 500a varying
d device_item ds
d 1a inz(x'01')
d 5i 0 inz(%size(device_item))
d token 32a
d item_hdr ds
d id 1a inz(x'02')
d item_len 5i 0
d item_data s 100a varying
item_data = '{"aps":{"alert":"You have mail"}}';
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);
我之前没有在IBM i上完成原始套接字,您可能需要将EBCDIC转换为ASCII。我不认为你需要担心小端与大端。
RPG可能不是最好的选择,鉴于Java PNS
等项目的存在,Java可能是更好的选择Stackoverflow没有大量的RPG / IBM i流量。您可以对以下内容做出更好的回应: