레이블이 PushNotification인 게시물을 표시합니다. 모든 게시물 표시
레이블이 PushNotification인 게시물을 표시합니다. 모든 게시물 표시

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 피드백 서버에 올린다.
당신은 가끔 피드백 서버에 연결하여 당신이 보낸 노티피케이션을 받지 않는 토큰들의 리스트를 다운로드 해야 한다.
그리고 그 토큰들에 대해서는 메시지 전송을 중단시켜야 한다.



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

Push Notification이란?

원문참조

iPhone 이나 iPod 터치의 애플리케이션은 종종 클라이언트-서버 모델 기반에 중점을 두기도 한다.
애플리케이션의 클래이언트 부는 장치에 설치된다.; 애플리케이션의 서버 사이드는 다수의 클라이언트 애플리케이션들에 데이터를 제공하는 것을 주 기능으로 한다. (그래서 이걸 "Provider(공급자)" 라고 한다.)
하나의 클라이언트 애플리케이션은 때때로 그 애플리케이션의 프로바이더와 연결해서 원했던 데이터를 다운로드 한다. 이메일과   SN 어플리케이션들은 이런 클라이언트 - 서버 모델의 예이다.

하지만 프로바이더가 다운로드할 새로운 데이터를 가지고 있을 때 애플리케이션이 그의 프로바이더에 연결되지 않았거나 장치에서 실행조차 되지 않은 경우라면?  이 대기중인 데이터에 대해서 어떻게 알 수 있을까? 푸시 노티피케이션들은 이런 딜레마에 대한 해결책이 된다.  하나의 푸시 노티피케이션은 프로바이터가 디바이스에 넘겨주는 짧은 메시지이다.; 이 디바이스는, 변화에 대해, 다운로드 될 데이터가 있는 클라이언트 애플리케이션의 사용자를 알려준다.  만약 이 사용자가 이 기능을 사용할 수 있고 애플리케이션이 완전하게 등록되어 있으면, 노티피케이션은 디바이스와 애플리케이션에 전달된다.

"Apple Push Notification Service" 에서 설명하는 APNS(Apple Push Notification Service) 는, 리모트-노티피케이션 기능을 위한 일차적인 기술이다.

사용자 관점에서 본 푸시 노티피케이션

당신이 iPhone을 사용하고 있다고 가정해 보자: 전화를 하고, 웹서핑을 하고, 음악을 듣는다. 당신의 아이폰에는  체스 애플리케이션이 설치되어 있다.  그리고 원격에서 플레이 하고 있는 친구와 함께 게임을 시작한다. 당신은 첫번째로 말을 움직였고(이것은 서버 애플리케이션에 기록되었다.), 이메일을 읽기 위해서 클라이언트 애플리케이션을 종료했다. 그 동안에, 당신의 친구는 당신의 움직임을 계산한다. 체스 애플리케이션의 서버는 이 움직임에 대해서 인지하고 당신의 디바이스가 더이상 연결되어 있지 않다는 것을 알고 APNS에 푸시 노티피케이션을 보낸다.
당신의 디바이스 - 엄밀히 말하자면 당신의 디바이스에서 돌아가고 있는 iPhone OS - 는 APNS 로 부터 노티피케이션을 받는다.
당신의 체스 어플리케이션이 지금 동작하고 있지 않기 때문에 iPhone OS 는 그림 1-1 과 같은 Alert 창을 보여주게 된다.

   그림 1-1 Push Notification Alert

여기에서 View 버튼을 누르면, 체스 애플리케이션이 실행되며, 프로바이더에 연결해서 새로운 데이터를 다운로드 받은 후 체스 판 UI를 친구의 움직임을 반영하여 조정하게 된다.(Close 버튼을 누르면 단순히 Alert 창을 닫는다.)

Alert 메시지를 나타내는 대신에 - 또는 Alert 메시지와 함께 - iPhone OS 에서는 타겟 애플리케이션의 아이콘 우측 상단에 그림 1-2와 같이 배지(badge) 번호를 표시할 수 있다.

그림 1-2 배지 넘버를 표시한 애플리케이션 아이콘

배지 넘버는 종종 그 애플리케이션을 위해 서버에서 가지고 있는 대기중인 아이템의 수를 반영하지만, 다른 의미로도 쓰일 수 있습니다.
배지 넘버는 그 애플리케이션의 특정된 그 어떤 숫자라도 나타낼 수 있습니다.
예를 들자면, 다운로드할 데이터 아이템의 수라던지, 읽지 않은(하지만 다운로드는 된) 이메일의 갯수라던지 하는것입니다.

Alert메시지나 배지 넘버와 함께 iPhone OS는 노티피케이션이 들어올때 특정 소리를 이용해서 사용자에게 알려줄수 있습니다.

Apple Push Notification Programming Guide

[링크 참조]
http://developer.apple.com/iphone/library/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction/Introduction.html


[ 서론 ]
푸시 노티피케이션 (리모트 노티피케이션이라고도 함) 은 데이터를 가지고 있는 서버의 IP와 지속적으로 연결하고 있으면서, 애플리케이션이 실행중이지 않을 때 디바이스에서 데이터를 받아 경고창, 소리 또는 배지를 이용해서 사용자에게 알려준다.
푸시 노티피케이션은 데스크탑 컴퓨터의 백그라운드 애플리케이션과 같은 용도를 가진다.
(알다시피, 백그라운드 애플리케이션은 모바일 기기에서는 허용되지 않는다.)

푸시 노티피케이션의 용법 가이드라인에 대해서는 iPhone Human Interface Guideline 에 있는  Enabling Push Notifications 를 보길 바란다.

이 문서에서는 푸시 노티피케이션이 무엇인가, 또 당신의 애플리케이션에서 푸시 노티피케이션의 기능을 어떻게 구현하는가에 대해서 논한다.
클라이언트 부의 구현은 Objective-C와 Cocoa Touch Framework으로 한다.
프로바이더 부의 구현은 TLS/SSL 기술과 스트리밍 소켓 기술이 도움이 될 것이다.


[이 문서의 구성]
이 문서는 다음과 같은 장으로 구성되어 있다.
  • "Push Notification 이란?" 푸시 노티피케이션이 무엇인지 설명한다.  어떻게 사용자에게 알려줄지, 그리고 개발자에게 어떤 이점들을 가져다 주며, 어떤 요구사항들이 있는지에 대해서 설명한다.
  • "Apple Push Notification Service" 프로바이더에서 클라이언트 애플리케이션에게 노티피케이션의 전송 및 라우팅(경로설정)을 하기 위한 Central Push Service 에 대해 설명한다.
  • "Provisioning and Development" 아이폰 개발자 프로그램 포탈로부터 권한을 얻는 과정과 개발환경 설정에 대해서 설명한다.
  • "Provicer Communication with Apple Push Notification Service" 프로바이더가 APNS 와 소통하기 위한 인터페이스와 요구사항에 대해 설명한다.
  • "iPhone OS Client Implimentation" iPhone OS 시스템에서 푸시(리모트) 노티피케이션을 제어 및 등록 하기 위해서 클라이언트 애플리케이션이 반드시 해야하는 것이 무엇인지 설명한다.

푸시 노티피케이션을 이해하는데 도움이 되는 유용한 정보에 대한 부가적인 소스는 다음을 보기 바란다.
  • Security Overview iPhone OS 및 Mac OS X 플랫폼에서 사용되는 보안 기술에 대해 설명한다.
  • UIApplication 과 UIApplicationDelegate 레퍼런스 문서는 클라이언트 애플리케이션을 위한 리모트 노티피케이션 API 를 설명한다.
  • RFC 5246 는 TLS 프로토콜에 대한 표준이다.
데이터 프로바이더와 APNS 사이의 안전한 커뮤니케이션을 위해서 Transport Layer Security(TLS) 이것의 이전 버전인 Secure Sockets Layer(SSL) 기술이 요구된다.
그 이상의 정보를 위해서는 암호화 관련 문서들을 참조하도록 하자.

내 블로그 목록

팔로어