HTML5 - WebSocket

ITWeb/개발일반 2011. 11. 2. 09:02
[참고사이트]
http://www.slideshare.net/zanylove/html5-websocket-5094806
http://www.slideshare.net/trustinlee/websocket
http://dev.w3.org/html5/websockets/
http://jwebsocket.org
http://code.google.com/p/phpwebsocket/


[Client]
. HTML5 WebSocket API 를 이용해서 작성

[Server]
. 별도의 Server 프로그램 작성 필요

phpwebsocket 으로 테스트 결과 정상적으로 동작함.
기본 원리는 브라우저에서 client port 생성하고 server port 로 접속 여러개의 브라우저 실행 시 브라우저 별로 port 가 다르게 뜨기 때문에 port 충돌 현상은 없음.
netstat -n 으로 확인 하면 됩니다.
2011.11.02 현재 safari 에서 정상동작 되며, 크롬에서는 객체 지원은 하나 동작하지는 않음.( phpwebsocket 으로 테스트 )

client/server 작성 코드들은 위 링크에 다 나와 있기 때문에 별도 작성은 하지 않습니다.
w3c 에 있는 interface 만.. 스크랩 합니다.

[Constructor(DOMString url, optional DOMString protocols),
 Constructor(DOMString url, optional DOMString[] protocols)]
interface WebSocket : EventTarget {
  readonly attribute DOMString url;

  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSING = 2;
  const unsigned short CLOSED = 3;
  readonly attribute unsigned short readyState;
  readonly attribute unsigned long bufferedAmount;

  // networking
  [TreatNonCallableAsNull] attribute Function? onopen;
  [TreatNonCallableAsNull] attribute Function? onerror;
  [TreatNonCallableAsNull] attribute Function? onclose;
  readonly attribute DOMString extensions;
  readonly attribute DOMString protocol;
  void close([Clamp] optional unsigned short code, optional DOMString reason);

  // messaging
  [TreatNonCallableAsNull] attribute Function? onmessage;
           attribute DOMString binaryType;
  void send(DOMString data);
  void send(ArrayBuffer data);
  void send(Blob data);
};




chrome 에서 왜 안되는지 확인을 해본 결과....
http://www.codeproject.com/KB/HTML/Web-Socket-in-Essence.aspx
http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-09
결국 phpwebsocket 의 code base의 protocol 과 latest protocol 에 차이가 있어서였다..ㅡ.ㅡ;;
※ Protocol 전문 참조 : http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-09#page-6

WebSocket request/response in the latest draft-ietf-hybi-thewebsocketprotocol-09:

Request
GET /demo HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: V2ViU29ja2V0IHJvY2tzIQ==
Sec-WebSocket-Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 8

Response
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: VAuGgaNDB/reVQpGfDF8KXeZx5o=
Sec-WebSocket-Protocol: chat


[Sec-WebSocket-Accept Handshake String 함수 - phpwebsocket 용]

function getComputeWebSocketHandshakeSecurityHash09 ($strKey) {

    $seedKey = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';

    $secWebSocketAccept = $strKey . $seedKey;

    $secWebSocketAccept = base64_encode(sha1($secWebSocketAccept, true));


    return $secWebSocketAccept;

}

 

- phpwebsocket 소스 중 server.php 에서 dohandshake 와 getheaders 함수를 수정해 줘야 합니다.

[getheaders 함수]
 if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)){ $key=$match[1]; } // 추가 코드
 return array($r,$h,$o,$key,$key1,$key2,$data); // $key 추가 됨

[dohandshake 함수]
 list($resource,$host,$origin,$strKey, $strkey1,$strkey2,$data) = getheaders($buffer); // $strKey 추가 됨
 if ($spaces1 == 0 || $spaces2 == 0 || $numkey1 % $spaces1 != 0 || $numkey2 % $spaces2 != 0) {
 ....
 // -->  이 부분에서 disconnect 와 return false; 가 되기 때문에 close 됨 그래서 코드 변경해야 함. protocol 버전에 맞게 코드 전체를 다시 작성 하면 되나 귀찮아서.. 그냥.. 내부에 hard coding 함. ^^;
     $upgrade  = "HTTP/1.1 101 Switching Protocols\r\n" .

                "Upgrade: websocket\r\n" .

                "Connection: Upgrade\r\n" .

                "Sec-WebSocket-Accept: " . getComputeWebSocketHandshakeSecurityHash09($strKey) . "\r\n" .

                "\r\n";

    socket_write($user->socket,$upgrade.chr(0),strlen($upgrade.chr(0)));

    $user->handshake=true;

    return true;

 } 

암튼 이렇게 해서 chrome 최신 버전에서랑 safari 에서 정상 동작 확인 끝. 
※ 추가, chrome 최신 버전(protocol 09)에서 websocket 사용시 send message 가 깨지는 현상이 있는 듯 함. 결국 최신 버전으로 테스트는 connection 까지 가능 하나 bidirectional sending 은 safari 에서 이전 protocol 로 테스트 하는게 아직까지는 정신 건강에 좋은 것 같내요.
: