HTML5 - WebSocket
ITWeb/개발일반 2011. 11. 2. 09:02http://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 로 테스트 하는게 아직까지는 정신 건강에 좋은 것 같내요.