2010년 3월 3일 수요일

Push Notification Service 서버 개발

내용출처 : Cocoa Touch for iPhone OS 3, WILEY  / http://www.wileydevreference.com

SSL을 사용하는 푸시 노티피케이션을 위한 애플리케이션 서버를 만들 수 있는 기술은 상당히 다양하며, 지금 이것들을 구성하는 내용에 대해서 모두 설명하는 것은 불가능 하다.
지금은 사용할 특정 기술을 하나 선택할 것이다.

이말인 즉슨, 이 예제에서는 Ruby를 사용한 푸시 노티피케이션 제공자의 구현방법을 보여주겠다는 것이다.

어떻게 애플리케이션을 작성하는지 또는 Ruby 코드를 어떻게 읽어야 하는지에 대한 자세한 내용은 다루지 않을 것이다.
지금은 일단 따라해 보자.
이 예제의 소스는 책에 전체 코드가 나와 있으며, 책의 웹사이트에서도 얻을 수 있다.

반드시 알아야 될 점은, 푸시노티피케이션 서비스는 전적으로 당신이 구성한 내용에 따라 실행이 달라진다는 것이다. 이 예제에서는 한가지 방법만을 알려줄 것이다.


Ruby 푸시 노티피케이션 공급자의 구현

Ruby로 푸시 노티피케이션 공급자를 구현하기 위해서는 OpenSSL, 연결 및 메시지 전송, 연결해제를 사용하기 위해 Ruby의 빌트인 서포트를 사용할 것이다.
당연히 다른 방법을 사용할 수도 있다.
특히, 모든 단일 메시지를 위해서 연결, 전송, 연결해제를 계속 하지는 말기 바란다.
솔직히, 이런 행동을 하면 애플은  그들의 서버를 공격하는 것으로 알고, 당신의 인증을 폐지시킬 것이다.
APNS 모델은 연결하고, 연결을 유지하고, 필요할때 메시지를 흘려보내는 개념을 기반으로 한다.  이런것은 또한 C, Python, Perl 등과 같은 다른 언어들로 수행할 수 있다.

잡담은 이쯤해 두고, 다음의 코드를 보도록 하자.
다음의 코드는 Ruby로 작성한 푸시 노티피케이션 공급자를 보여준다.


A Push Notification Supplier Implemented in Ruby
#!/usr/bin/ruby
# ./notify.rb '' ''
require 'socket'
require 'openssl'
# just checking our arguments...
if(ARGV.length < 2 or ARGV[0].length < 32)
    puts "Usage: ./notify.rb '' ''"
    exit(-255)
end
# strip out the space in the token
# the token is copied from an NSLog in our client app
tokenText = ARGV[0].delete(' ')
messageText = ARGV[1]
# pack the token to convert the ascii representation  back to binary
tokenData = [tokenText].pack('H*')
#construct the payload
payload = "{\"aps\":{\"alert\":\"#{messageText}\", \"badge\":1}}"
#construct the packet
packet = [0, 0, 32, tokenData, 0, payload.length, payload].pack("ccca*cca*")
# read our certificate and set up our SSL context
cert = File.read("devcerts.pem")
openSSLContext = OpenSSL::SSL::SSLContext.new
openSSLContext.cert = OpenSSL::X509::Certificate.new(cert)
openSSLContext.key = OpenSSL::PKey::RSA.new(cert)
# Connect to port 2195 on the server.
sock = TCPSocket.new('gateway.sandbox.push.apple.com',2195)
#do our SSL handsaking
sslSocket = OpenSSL::SSL::SSLSocket.new(sock, openSSLContext)
sslSocket.connect
#write our packet to the stream
sslSocket.write(packet)
#cleanup
sslSocket.close
sock.close

이 코드에서 푸시 노티피케이션을 보내는 과정에 대해서 자세히 보도록 하자.

첫째로, 당신은 메시지와 디바이스 ID를 커맨드라인 파라미터를 통해서 얻는다.
그리고 이것을 이용해 APNS 서버에 보낼 패킷을 구성한다.

Constructing Your Packet
# strip out the spaces in the token
# the token is copied from an NSLog in our client app
tokenText = ARGV[0].delete(' ')
messageText = ARGV[1]
# pack the token to convert the ascii representation  back to binary
tokenData = [tokenText].pack('H*')
#construct the payload
payload = "{\"aps\":{\"alert\":\"#{messageText}\", \"badge\":1}}"
#construct the packet
packet = [0, 0, 32, tokenData, 0, payload.length, payload].pack("ccca*cca*")

기본적으로, 당신은 커맨드라인 인자를 얻어서 메시지와 payload에 넘겨질 직렬화된 JSON 오브젝트를 구성한다. 메시지는 JSON 딕셔너리에 "alert" 이라는 키를 이용해 위치 시킨다.
또 다른 키인 "bedge" 에는 1을 설정했다.
마지막으로, 이 딕셔너리 오브젝트를  "apt" 키와 연관된 곳에 넣는다.

다음은, 디스크에서 당신의 인증서를 읽어오는 것과 관련된 코드 이다.
Reading the Certificates
# read our certificate and set up our SSL Context
cert = File.read("devcerts.pem")
openSSLContext = OpenSSL::SSL::SSLContext.new
openSSLContext.cert = OpenSSL::X509::Certificate.new(cert)
openSSLContext.key = OpenSSL::PKey::RSA.new(cert)

여기에서 중요한 부분은 iPhone Developer Portal 에서 언제 당신의 인증서를 받을 것인지에 대한 것이다. 이것은 .p12 포멧으로 되어 있다.
대부분의 OpenSSL 라이브러리들은 .pem 포멧의 인증서로 동작하는것을 선호한다.
그러므로, .p12 포멧에서 .pem 포멧으로 변경해 주어야 한다.
이렇게 하기 위해서 다음의 명령어를 실행시킨다.

openssl pkcs12 -in Certificates.p12 -out devcerts.pem -nodes -clcerts

이 파일을 얻으면, 이것을 이용해서 OpenSSL 컨텍스트를 생성할 수 있다.
이 컨텍스트에서 당신의 인증서에서 얻은 정보로 cert와 key 속성을 설정한다.

다음으로, APNS 서버로의 연결을 오픈한다.
한번 연결을 오픈하면, TCP 소켓을 이용하는 새로운 SSLSocket 을 초기화 한다.
SSL socket 에서 connect 를 호출하면 SSL 은 handshaking을 수행한다.

Connecting to the Server and Sending Your Packet
# Connect to port 2195 on the server
sock = TCPSocket.new('gateway.sandbox.push.apple.com', 2195)
# do our SSL handshaking
sslSocket = OpenSSL::SSL::SSLSocket.new(sock, openSSLContext)
sslSocket.connect
#write our packet to the stream
sslSocket.write(packet)

마침내, 당신은 서버에 패킷을 보냈다.

Pushing Notifications

이제 간단한 명령어를 실행함으로써 노티피케이션 제공자를 실행시킨다.
./notify.rb '' ''
여기에서 토큰은 당신의 클라이언트 애플리케이션으로부터 받은 것이다.
테스트 목적이라면, 콘솔을 이용한 간단한 로그를 날리는 애플리케이션을 만들 수 있다.
그렇다면, 저 명령어를 커맨드 라인에 붙여 넣으면 된다.
실제 구현은 소켓을 사용하는 당신의 서버로 토큰을 날리는 메커니즘을 작성해야 하며 이런 절차는 자동화 시키도록 한다.

디바이스에서 이 메시지를 받으면 스크린에 표시될 것이다.




Checking delivery using feedback

만약에 사용자가 iPhone에서 당신의 애플리케이션을 삭제하면, 노티피케이션을 계속 보내야 되는지 알수가 없다.

받은 노티피케이션들은 더이상 표시해 줄 애플리케이션이 없다.
디바이스 또한 APNS 서버에 전송될 수 없다는 공지를 해준다.
APNS 서버는 그 다음으로 이 디바이스에 대한 리스트를 APNS 피드백 서버에 올린다.
당신은 가끔 피드백 서버에 연결하여 당신이 보낸 노티피케이션을 받지 않는 토큰들의 리스트를 다운로드 해야 한다.
그리고 그 토큰들에 대해서는 메시지 전송을 중단시켜야 한다.



===================================
아오.. 루비는 모르는데 어쩔꺼임?

댓글 없음:

댓글 쓰기

내 블로그 목록

팔로어