학습자료(~2017)/네트워크

[LONG POLLING][COMET][PUSH SERVER] 푸시 서버

단세포소년 2012. 8. 2. 21:08
반응형


보통의 클라이언트, 서버 모델은 클라이언트의 연결 요청이 이루어 지고 클라이언트의 작업요청에 대해 서버가 응답해주는 형태이다. 즉 서버는 클라이언트가 자신에게 요청을 하지 않는다면 응답해주지 않는다.

예를 들어 하나의 웹페이지가 있다. 이 웹페이지는 공지사항을 띄워주는 웹페이지다. 기본적인 웹페이지는 새로운 공지사항이 생겼는지 확인하기 위해 유저가 새로고침을 누를 것이다. 혹은 새로고침을 주기적으로 반복하는 스크립트를 넣을 것이다. 공지사항이 새로 올라오지도 않았는데 새로고침을 통해 서버에게 요청을 보내야 하고 이는 서버에 많은 부담을 준다.

push  server는 클라이언트의 요청이 오면 응답해주는 방식이 아닌 서버가 클라이언트에게 공지사항과 같은 무엇인가 통지해주기 위한 방법이다. 다시 말해 클라이언트의 요청이 없이도 서버는 클라이언트에게 응답하는 방식이다.

일반적인 소켓 프로그래밍에서는 클라이언트와 서버가 연결이 되면 그 연결이 유지되므로 push server는 일반적인 서버모델과 다를 바가 없다. 하지만 HTTP 프로토콜을 사용하는 웹프로그램/웹페이지 같은 경우는 HTTP 프로토콜의 특성상 연결이 유지되지 않는다. 서버가 클라이언트에게 통지해줄수 있는 방법이 없다는 것이다. HTTP 서버는 매우 수동적인 존재이다.

이런 HTTP 프로토콜의 특성때문에 실제 push server 구현은 되지 않는다. 하지만 push server 의 효과와 비슷한 모델들이 등장한다. 
웹서버의 push server 모델은 POLLING, LONG POLLING, STREAM 이 존재한다.
POLLING 은 클라이언트가 끊임없이 웹서버에게 새로운 내용이 있는지 물어보는 방식이다.
LONG POLLING 은 클라이언트가 웹서버에게 새로운 내용이 있는지 물어보았을 때 웹서버에 새로운 내용이 없다면 대답해주지 않다가 새로운 내용이 생기면 이때 대답해주는 방식이다.
STREAM은 웹서버의 응답 헤더의  content-length 를 이용한 방법이다. 응답헤더의 content-length 가 존재하지 않는다면 클라이언트는 연결이 끊길때 까지 응답을 받아들인다. 즉 한번의 요청에 대해 끊임없는 응답을 보내는 방식이다. 이 방식은 한번의 요청만 있으면 되므로 효율은 좋지만 error 처리에 매우 취약하다.

요즘은 대체로 LONG POLLING 방식을 추구하는 편이다.

나도 구현해 본 적이 없고 글로만 이해했기 때문에 아주간단하게(나만 볼수있게) 정리해 봤다. 아래의 참고사이트를 통해 이해하라. 실습을 통해 구현하게 되면 블로그에 추가내용을 올리겠다. (자바나 서블릿등 웹프로그래밍의 기본지식은 필요하다.)

http://mygony.com/archives/2535

http://ajaxpatterns.org/HTTP_Streaming

http://www.ape-project.org/ - ajax push engine

http://www.caucho.com/resin-3.1/doc/resin-comet.xtp - Resin: Application Server | Java EE Web Profile Certified Cloud Optimized | DevOps Friendly

http://en.wikipedia.org/wiki/Push_technology

http://en.wikipedia.org/wiki/Comet_(programming)

http://stackoverflow.com/questions/333664/simple-long-polling-example-code - long polling simple example

http://ko.wikipedia.org/wiki/XAMPP - simple web server

COMET 구현 기법 
http://www.uengine.org:8088/wiki/index.php/Comet_%EA%B5%AC%ED%98%84_%EA%B8%B0%EB%B2%95

Push technology
http://en.wikipedia.org/wiki/Push_technology 

COMET 소개/ 이벤트 중심 웹개발
http://www.ibm.com/developerworks/kr/library/wa-reverseajax1/index.html
http://www.ibm.com/developerworks/kr/library/wa-reverseajax2/index.html
http://www.ibm.com/developerworks/kr/library/wa-reverseajax3/index.html
http://www.ibm.com/developerworks/kr/library/wa-reverseajax4/index.html
http://www.ibm.com/developerworks/kr/library/wa-reverseajax5/index.html

commet 제품 비교 사이트
http://cometdaily.com/maturity.html



 예제 참고

http://www.uengine.org:8088/wiki/index.php/Comet_%EA%B5%AC%ED%98%84_%EA%B8%B0%EB%B2%95#XHR_long_polling
http://www.zeitoun.net/articles/comet_and_php/start
http://blog.naver.com/PostView.nhn?blogId=playse444&logNo=150128458138
http://helloworld.naver.com/helloworld/1052 - 강추
http://breathair.tistory.com/113 - XMLHttpRequest 설명
http://streamhub.blogspot.kr/2009/07/tutorial-building-comet-chat.html
http://www.ibm.com/developerworks/kr/library/wa-reverseajax1/ - XHR, multipart
http://tkjeon.tistory.com/6
http://stackoverflow.com/questions/5894019/accurate-long-polling-example
http://stackoverflow.com/questions/333664/simple-long-polling-example-code
http://www.ibm.com/developerworks/kr/library/wa-reverseajax2/index.html - WebSocket
http://jjeong.tistory.com/m/post/view/id/526 - multipart/x-mixed-replace 와 xhr 사용

http://dsheiko.com/weblog/html5-and-server-sent-events - html5 server sent event

















정리

1. comet 정의

 comet 은 브라우저에서 명시적인 요청없이 웹서버에서 브라우저로 데이터를 push 하는 웹 어플리케이션 모델이다. 

comet은 이 상호작용을 위한 다양한 기술을 포함하는 용어이다.

2. 방식

 Polling
 

 

 기본적인 http 프로토콜이다. 특정 요청에 대해 이벤트가 있던 없던 응답을 보낸다.

요청에 대한 서버 부담이 크지 않거나 실시간 메시지 전달이 크게 중요하지 않은 서비스에 적합하다.
요청주기는 조절 할 수 있지만 요청주기가 너무 길다면 서버 상태 변화를 빠르게 인지하지 못하고 요청주기가 너무 짧다면 서버 상태 변화는 빠르게 인지하지만 서버에 많은 부하를 줄 수 있다. 전체적으로 서버부하와 네트워크 트래픽을 많이 발생시킨다.

네트워크 프로그래밍의 non-block 방식이랄까?


Long Polling 

 


 Polling 모델과 차이점은 클라이언트의 요청에 대해 서버에서 이벤트 발생시에만 응답을 준다는 것이다. Polling 과 Long Polling 의 차이점은 즉 클라이언트 요청에 대한 서버의 대처방식이다.
Long Polling 은 실시간 메시지 전달이 중요하고 서버의 상태 변경이 빈번히 발생하지 않는 서비스에 적합하다. Polling 방식에 비해 요청/응답 트랜잭션이 덜 하다. 따라서 서버와 네트워크에 부하가 적다.

네트워크 프로그래밍에서 block 방식이랄까? 조금 다른 점은 네트워크 block 방식에서는 응답을 받았다고 연결을 끊지 않지만 Long Polling 에서는 응답을 받으면 연결을 끊고 다시 연결을 한다는 점이다.




Streaming 

 

 Streaming 은 요청후에 연결을 지속하여 계속적인 응답을 받는 것이다. Polling, Long Polling 과 다르게 응답을 받은후 연결을 종료하지 않는다. 서버는 상태변화(이벤트)시 이 스트림을 통해 응답을 지속적으로 보낸다. 이 모델의 경우 요청이 단 한번만 이루어지기 때문에 서버와 네트워크 트래픽에 부하를 덜 준다. 하지만 응답데이터의 시작과 끝을 알수 없기 때문에(스트림이니까) 데이터의 유효성을 체크하는 루틴이 필요하다.

네트워크 프로그래밍의 단방향 모델이랄까? 

3. 세부방식

 모델 구현법 

 Polling & Long Polling

 url call

 XMLHttpRequest 
 Streaming 

 XMLHttpRequest

 IFrame 

 Htmlfile 

 Multipart 

 Server Sent Event 
 Web Socket

Polling 과 Long Polling 은 클라이언트에서 구현이 동일하다. Long Polling 은 서버쪽의 특별한 기능이 필요하다.(응답을 이벤트 발생시에만 보내는 것)


 구현법설명 

 url call (callback polling)

 가장 기본적인 브라우저 구현방식이다. 
 대체로 서버에서 <script> 코드와 데이터를 클라이언트로 보내어 클라이언트(브라우저)에서 해석 실행하게 하는 원리이다. 이를 callback polling 이라 한다.

 XMLHttpRequest 

 XHR은 callback polling 과 다르게 script 코드 없이 필요 데이터만을 보낼수 있다. 대체로 xml, json 등으로 응답 데이터를 전달한다.
 XHR은 보안상 제약이 있다. 하지만 에러와 상태를 더 정교하게 다룰 수 있다는 장점이 있다. Long Polling 과 Streaming 모델에서 사용된다.

 IFrame

 inner frame 은 부모 frame 내에 자식으로 frame 을 넣고 요청과 응답을 자식 frame에서 처리하도록 하는 것이다.
 iframe 을 지원하는 모든 브라우저에서 작동한다.
 http/1.1 의 chunked 인코딩 방식을 기반으로 서버와 연결을 맺어둔다.
 모든 연결과 데이터가 html 태그를 통해 브라우저에 의해 처리되므로 안정적인 오류 처리를 구현하거나 연결 상태를 추적할 방법이 없다. 그래서 어느 쪽에서든 연결이 끊어지는 때를 알 수 없다.
 iframe 을 이용하므로 웹 부라우저의 상태 표시줄에 연결 중임을 계속 표시하고 서버 응답시 클릭하는 소리가 난다.

 htmlfile

 htmlfile 이라는 ActiveX Object를 이용하는 방식으로 IFrame의 단점(클릭소리, 연결중 표시)을 해결 할 수 있다.
 ActiveX 는 마이크로소프트의 인터넷 익스플로러에서만 지원하므로 익스플로러에서만 동작한다. 

 Multipart

 서버에서 응답을 content-type 을 multipart/x-mixed-replace 로 보내는 방식으로 multipart/x-mixed-replace 은 서버 푸시와 http 에서 스트림 구현을 위해 개발되었다.
클라이언트(브라우저)는 XHR(XMLHttpRequest) multipart 를 이용하여 구현할 수 있다.
현시 xhr.multipart=true
; 한다.

 Server Sent Event 
(event-source object)

 HTML5 에 정의된 서버 푸시 기술의 표준이다.
 서버는  content-type 이 application/x-dom-event-stream 인 데이터를 보내면 클라이언트(브라우저)는 이벤트와 매칭되는 callback 함수를 호출한다.

 Web Socket

 HTML5에 처음 도입된 WebSocket은 comet 보다 훨씬 더 최신의 기술이다. WebSocket은 양방향 전이중 통신 채널을 사용하며 많은 브라우저에서 지원하고 있다. WebSocket은 몇가지 특수 헤더와 함께 WebSocket 핸드쉐이크라고 하는 HTTP요청을 통해 연결이 열린다. 이 연결은 계속 유지되며 원시 TCP 소켓을 사용하는 것처럼 javascript에서 데이터를 쓰고 수신할 수 있다.
 기본 comet 에 비해 WebSocket을 지원하는 클라이언트는 속도가 더 빠르고 요청을 덜 생성하며 대역폭을 덜 소비한다.
 WebSocket 을 지원하지 않는 브라우저의 경우 일부 라이브러리는 FlashSocket(Flash를 통한 소켓)으로 변경할 수 있다. 이런 라이브러리는 보통 공식 WebSocket API를 제공하며 웹사이트에 포함된 숨겨진 Flash 컴포넌트에 호출을 위임하여 이를 구현한다. 


 FlashSocket (참고)

 장점 : FlashSocket은 HTML5 WebSocket을 지원하지 않는 브라우저에서도 WebSocket 기능을 투명하게 제공한다.

 단점 : flash 플러그인을 설치해야한다.(보통 모든 브라우저에는 이미 설치 되어 있음)
          flash 컴포넌트가 도메인 권한을 포함한 정책 파일을 검색하는 HTTP 요청을 할 수 있 도록 방화벽의 포트 843이 열려 있어야한다. 포트 843에 연결할 수 없는 경우 라이브러리를 변경하거나 오류가 발생해야한다. 이런 처리를 모두 수행하는 데는 라이브러리에 따라 최대 3초가 걸리므로 웹 사이트의 속도를 떨어뜨리게된다.
         클라이언트가 프록시 서버 뒤에 있는 경우 포트 843에 대한 연결이 거부될 수 있다.

 WebSocketJS 프로젝트는 브릿지를 제공한다. 이 프로젝트에는 최소한 Flash 10이 필요하고 Firefox 3, internet Explorer 8, 9 까지 Websocket 지원을 제공한다.


클라이언트(브라우저)는 XMLHttpRequest 를 Polling, Long Polling, Streaming 구현시 다 사용할 수 있다. 좋다.
WebSocket 등 더 좋은 기술을 사용할 수 있지만 지원하지 않는 브라우저를 위해 차선택인 comet 모델을 지원할 수 있도록 하는 것이 좋다.


4. 예제


Long Polling - url 호출 (JSONP)

클라이언트 요청
 var script = document.createElement('script'); script.src = 'http://domain.com/path/to/server.cgi?callback=callback_function_name' ;

서버 응답
callback_function_name( {some:data, in_any:format, you:want} );

 클라이언트는 script 를 요청하고 url 에 callback 파라미터를 통해 처리함수를 넘겨준다.

서버는 callback 파라미터로 넘어온 처리함수를 호출할수 있도록 하고 내부 인자로 JSON 혹은 XML , 일반 데이터를 얻어 보내준다. 위와 같이 JSON 데이터를 콜백함수로 감싸는 것을 JSONP 라고 한다.

클라이언트는 script 코드를 실행하므로써 자신이 원하는 처리를 할 수 있다.

구현은 간단하나 서버의 응답이 script 코드를 넘겨주므로 우리가 원하던 JSON, XML 데이터로만으로 받을 수는 없다.

<script> 태그의 특성상 src에 지정한 리소스를 모두 읽어온 후에 해석하고 실행하기 때문에 스트리밍 방식을 사용할 수 없다. 하지만 <iframe> 태그는 src에 지정한 리소스를 모두 읽지 않아도 받은 데이터를 즉각즉각 해석하기 때문에 스트리밍이 가능하다.

 장점 : 여러 브라우저에서 사용 가능하며 포트, 도메인등의 제약을 받지 않는다.

 단점 : 에러나 http의 상태를 다룰 수 없고 스트리밍 방식을 사용할 수 없다.


Long Polling - XMLHttpRequest (XHR) 

클라이언트 요청
 function longPoll(url, callback) {
   var xhr = new XMLHttpRequest();
   xhr.onreadystatechange = function() {
   if(xhr.readyState == 4) {

// 응답이 완료되면 서버로
//재연결 요청보내기
   callback(xhr.responseText);
   xhr.open('GET', url, true);
   xhr.send(null);
  }
}

// 서버로 요청 연결하기

xhr.open('POST', url, true);

xhr.send(null);

}

서버 응답 - XML , JSON , 일반 데이터
{some:data, in_any:format, you:want} 


 url 호출을 이용한 script 방식과 비슷하나 서버 응답 데이터가 script 로 감싸여 있지 않는다. 즉 데이터 그 자체로만으로 반환된다.

 XMLHttpRequest 라는 객체를 사용한다.

 장점 : 에러와 http 상태를 더 정교하게 다룰 수 있다.

 단점 : 보안 제약이 있다.(몇몇 브라우저에서 XHR을 통한 스트리밍이 되지 않는다. )


 Streaming - XHR streaming

 클라이언트 요청

function xhrStreaming(url, callback) {
  var xhr = new XMLHttpRequest();
  xhr.open('POST', url, true);
  var lastSize;

// 최신 텍스트를 가져오기 위한 위치
  xhr.onreadystatechange = function() {
  var newTextReceived;

if(xhr.readyState > 2) {
  // 최신 텍스트 가져오기
  newTextReceived =  xhr.responseText.substring(lastSize);

  lastSize = xhr.responseText.length;
  callback(newTextReceived);

   }

if(xhr.readyState == 4) {

// 응답이 완료되면
//새로운 요청을 다시 만든다

  xhrStreaming(url, callback);

  }

}

// 서버로 요청 연결하기
  xhr.send(null);


서버 응답 - XML , JSON , 일반 데이터 (Content-Length = 0)
{some:data, in_any:format, you:want} 

 XHR Long Polling 과 비슷하나 readyState 상태가 완료 상태가 아닌 데이터의 일부를 받았을때 처리를 한다는 것에서 다르다. 또한 서버는 연결을 끊지 않고 계속적으로 데이터를 보낸다.

 데이터의 앞과 뒤가 없어 데이터의 유효성을 체크하는 기능이 필요하고 응답 데이터는 계속적으로 쌓이므로 주기적으로 데이터를 없애거나 주기적으로 연결 해제후 다시 연결하는 방식을 사용해야한다.

원리 :
1. onreadystatechange 이벤트가 발생하면 readyState 변수를 확인한다.
2. readyState 변수가 3(혹은 4) 일때, 요청 연결 후부터 현재까지 서버로부터 받은 결과에 접근한다.
3. 결과 중 마지막 이벤트에 해당하는 텍스트를 가지고 온다.


  장점 : 응답 결과의 텍스트 뿐 아니라 헤더에도 직접 접근할 수 있고 장애도 비교적 쉽게 처리할 수 있다.
  단점 : 몇몇 브라우저에서 readState 가 3일때 보안상의 이유로 응답결과에 접근하지 못한다.


 Streaming - IFrame Streaming

 클라이언트 요청

예1)

function foreverFrame(url, callback) {
  var iframe = body.
  appendChild(
  document.createElement("iframe"));
  iframe.style.display = "none";
  iframe.src = url + "?callback=parent.foreverFrame.callback";
  this.callback = callback;
}

예2)

var iframe = document.getElementById(iframe_id);
if (!iframe) {
    iframe = document.creatElement('iframe');
    iframe.id = iframe_id;
    document.body.appendChild(iframe);
}

iframe.style.position = 'absolute';
iframe.style.top = '-100px';
iframe.style.left = '-100px';
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.src = 'http://server/push.cgi';


서버 응답

<script>parent.foreverFrame.callback("the first message");</script>
<script>parent.foreverFrame.callback("the second message");</script>

 내부 프레임이라는 html 객체를 이용한다. iframe 은 frame 내부에서 보이지 않게 요청을 보내고 응답결과를 실행한다.
 브라우저 특성에 따라 <iframe>의 display 속성이 none 일 경우 iframe을 폼 전송의 target으로 설정할 수 없으므로 크기를 매우 작게 만들어 안보이는 영역에 두는 방식을 사용하는 것이 좋다.

서버 응답의 경우 주기적으로 clean 코드를 두어 계속적으로 쌓이는 <script> 코드를 제거해주어야한다.

 장점 : 폭넓은 호환성이 있다. 왠만한 오래된 브라우저도 <iframe>태그를 지원한다.

 단점 : 에러를 제대로 다룰 수 없다. http 상태를 다룰 수 없다 . 모바일 브라우저에서 사용할 수 없다. 웹 브라우저의 기본 보안 정책인 동일 출처 정책(same-Origin Policy)의 영향을 받으므로 도메인이나 스키마, 포트가 다른 문서간에는 사용할 수 없다.
클릭소리와 상태 표시줄에 연결중임을 계속 표시한다.


 Streaming - htmlfile streaming

 클라이언트 요청

예1)

// we were served from child.example.com but
// have already set document.domain to example.com
var currentDomain = "http://exmaple.com/";
var dataStreamUrl = currentDomain+"path/to/server.cgi";
var transferDoc = new ActiveXObject("htmlfile"); // !?!

// make sure it’s really scriptable
transferDoc.open();
transferDoc.write("<html>");
transferDoc.write("<script>document.domain='"+currentDomain+"';</script>");
transferDoc.write("</html>");
transferDoc.close();

 // set the iframe up to call the server for data
var ifrDiv = transferDoc.createElement("div");
transferDoc.appendChild(ifrDiv);

// start communicating
ifrDiv.innerHTML = '<iframe src="'+dataStreamUrl+'"></iframe>';


예2)

function foreverFrameByHtmlfile(url, callback) {
// 명시적인 가비지 콜렉터 호출을 위해
//'var transferDoc...'라고 하지 않음 

transferDoc = new ActiveXObject("htmlfile");
transferDoc.open();
transferDoc.write("<script>" + "document.domain='" + document.domain + "';" +"</script>");
transferDoc.close();
var ifrDiv = transferDoc.createElement("div");
transferDoc.body.appendChild(ifrDiv);
ifrDiv.innerHTML ="<iframe src="+ url +"></iframe>";
transferDoc.callback = callback;

}

function foreverFrameClose() { 
// transferDoc 참조를 없애고,
// 명시적으로 가비지 콜렉터를 호출함
transferDoc = null;
CollectGarbage();

}

// 페이지가 이동되거나
// 창이 닫힐 때 호출함수 지정
window.onunload = foreverFrameClose; 


<iframe> 대신 ActiveX 콘트롤의 htmlfile 객체를 이용하는 방법이다. 따라서  인터넷 익스플로러의 경우만 사용할 수 있다.

기본적인 내용은 iframe 와 동일하다.


 Streaming - multipart streaming (XHR multipart streaming)

 클라이언트 요청

//we create a norma xhr object (this is the mootools way but can be anything)
this.tunnel = new Request({
url: this.options.urlServer,
method: 'get',
header: ''
});

//we active the multipart option of the xhr object
this.tunnel.xhr.multipart = true ;
//we change the onload function, and everytime we got a readyState == 4, it means that we get a new part of data !
this.tunnel.xhr.onload = function (event) {
if (event.target.readyState == 4 ) {
alert('data pushed :'+event.target.responseText) ;
this.fireEvent('dataPushed', [event.target.responseText, event.target.responseXML])
}
else {
this.fireEvent('error', "Error xhr : readyState: "+event.target.readyState)
}
}.bind(this.tunnel);



서버 응답
코드 예)
this.pw.print("Content-Type: multipart/x-mixed-replace;boundary=myboundary");
this.pw.print("Content-Type: text/json\r\n\r\n"+_the_data_to_push+"\r\n\r\n--myboundary\r\n"); 


응답 예)

HTTP/1.1 200 OK
Content-Type: multipart/x-mixed-replace; boundary=--myboundary

--myboundary
Content-Type: text/json
Content-length: 12345

[json data]

--myboundary
Content-Type: text/json
Content-length: 45678

[json data]

...


 멀티파트는 데이터를 구분자(위의 예제에서는 --myboundary)로 나누므로써 데이터의 시작과 끝을 정확히 표현하고 스트리밍 방식으로 데이터를 계속 넘겨주기에 좋은 방법이다.

multipart 의 자세한 내용은 google 검색을 활용하라.

 장점 : 여러 브라우저에서 지원하고 ,  XHR 의 보안제약인 readyState 가 3 일때 응답 데이터에 접근하지 못하는 제약도 피한다.

 단점 : 


 streamint - Server Sent Events (the event-source object)

클라이언트 요청

예1)

document.getElementsByTagName("event-source")[0] .addEventListener(" a_specific_id ", eventHandler, false);
function eventHandler(event)
{
    // Alert time sent by the server
    alert(event.data); 
}

예2)

//create the event-source object in the dom
this.tunnel = document.createElement("event-source");
//we add a specific listenenr on the event-source.
this.tunnel.addEventListener("a_specific_id", this.decodeJSON.bindWithEvent(this), false);
//we set the src attribute = the server URL
this.tunnel.setAttribute("src", "your java comet server url");

//finaly the .decodeJSON function called every time a data will be pushed by the server
this.decodeJSON: function (_textResponse) {
_textResponse = _textResponse.data ;
}


예3)

var eventSource = new EventSource("server.asp");
eventSource.addEventListener("message", function(e){          
      alert(e.data);
    }
,false);

서버 응답

코드 예)
예1)
this.pw.print("Content-Type: application/x-dom-event-stream");
this.pw.print("Event: a_specific_id\ndata: "+_the_data_to_push+"\n\n");

예2)

<?php
header("Content-Type: application/x-dom-event-stream");
while(true) {
    echo "Event: a_specific_id\n";
    echo "data: data_to_push\n";
    echo "\n";
    flush();
}
?>


예3)

<?php
header("Content-Type: text/event-stream\n\n");
echo 'data: ' . time() . "\n";
?>


응답 데이터 예)

Content-Type: application/x-dom-event-stream

Event:a_specific_id\r\n
data:data_to_push\r\n\r\n


  html5 에 정의된 서버푸시 기술의 표준인 server sent events api를 사용한다. 
  application/x-dom-event-stream 의 경우 이벤트 명을 명시적으로 표현(Event:a_specific_id)하므로써 클라이언트에서 처리루틴 결정을 확실히 할 수 있다. (Content-Type: text/event-stream 은 이벤트 명이 포함되 있지 않다.)

 장점 : 심플한 자료구조와 인터페이스, 통신 매커니즘을 정의하고 있으며 일반적인 DOM 이벤트 형태로 수신 데이터를 처리 할 수 있는 등 서버푸시 구현이 매우 간단해진다.

 단점 : 


Streaming - WebSocket 

 클라이언트 요청

var ws = new WebSocket('ws://127.0.0.1:8080/async'); 
ws.onopen = function() { 
    // called when connection is opened 
}; 

ws.onerror = function(e) { 
    // called in case of error, when connection is broken in example 
}; 

ws.onclose = function() { 
    // called when connexion is closed 
}; 

ws.onmessage = function(msg) { 
    // called when the server sends a message to the client. 
    // msg.data contains the message. 
}; 

// Here is how to send some data to the server 
ws.send('some data'); 
// To close the socket:
ws.close();


서버 응답

jetty 컨테이너용 websocket 핸들러

public final class ReverseAjaxServlet extends WebSocketServlet { 
 @Override 
    protected WebSocket doWebSocketConnect(HttpServletRequest request,
                                           String protocol) { 
        return [...] 
    } 
}

WebSocket 구현
class Endpoint implements WebSocket { 

    Outbound outbound; 

    @Override 
    public void onConnect(Outbound outbound) { 
        this.outbound = outbound;    
    } 

    @Override 
    public void onMessage(byte opcode, String data) { 
        // called when a message is received 
        // you usually use this method 
    } 

    @Override 
    public void onFragment(boolean more, byte opcode, 
                           byte[] data, int offset, int length) { 
        // when a fragment is completed, onMessage is called. 
        // Usually leave this method empty. 
    } 

    @Override 
    public void onMessage(byte opcode, byte[] data, 
                          int offset, int length) { 
        onMessage(opcode, new String(data, offset, length)); 
    } 

    @Override 
    public void onDisconnect() { 
        outbound = null; 
    } 
}


Websocket 구현

class Endpoint implements WebSocket { 

    Outbound outbound; 

    @Override 
    public void onConnect(Outbound outbound) { 
        this.outbound = outbound;    
    } 

    @Override 
    public void onMessage(byte opcode, String data) { 
        // called when a message is received 
        // you usually use this method 
    } 

    @Override 
    public void onFragment(boolean more, byte opcode, 
                           byte[] data, int offset, int length) { 
        // when a fragment is completed, onMessage is called. 
        // Usually leave this method empty. 
    } 

    @Override 
    public void onMessage(byte opcode, byte[] data, 
                          int offset, int length) { 
        onMessage(opcode, new String(data, offset, length)); 
    } 

    @Override 
    public void onDisconnect() { 
        outbound = null; 
    } 
}

메시지 보낼때

if (outbound != null && outbound.isOpen()) {
    outbound.sendMessage('Hello World !');
}


 websocket 을 이용하여 데이터 스트림을 생성하고 마치 tcp/ip 통신을 하듯이 프로그래밍을 하면 된다.

 http://html5korea.co.kr/html5lec/900 여기를 참고하기 바란다.

 장점 : 

 단점 : 


참고 : http://breathair.tistory.com/113XMLHttpRequest(XHR) 설명 

 

 





반응형