'websocket'에 해당되는 글 5건

  1. 2011.11.02 websocket #4 (웹소켓의 한계) (1)
  2. 2011.10.31 websocket #3
  3. 2011.10.31 websocket #2 (node.js 설치) (1)
  4. 2011.10.28 websocket #1
  5. 2011.07.12 WebSocket이 빠르긴 하구나..

websocket을 직접 해보니 브라우져 지원 여부를 확실히 한계가 있다는 게 느꼈다..
기존 언어에서 통신 관련 옵션을 지원했던 거라든가. 좀 더 명확한 api가 있으면 좋겠다는 생각을 했다. 


그래서 socket.io에 이런 내용이 없나 봤더니.. 좀 있다. 
http://socket.io/#announcement



  1. You need to think about how you encode and interpret messages.
  2. It's hard to achieve interoperability with 3rd-party code.
  3. Logic for "connecting" or "disconnecting" specific parts of the application are inexistent.
  4. Authentication, error-handling for different subsets of functionality introduce even more difficulties.

     

아웃사이더님이 잘 요약해주셨다. 한글자료이니 잘 참조하면 될듯 하다. 
http://blog.outsider.ne.kr/668

 

연결에 대해서 명확한 개념을 socket.io에 구현했다. 

Websocket 코드 
var a = new WebSocket();

a
.onmessage = function (msg) {
 
var msg = JSON.parse(msg);
 
if (msg.type == 'chat') {
   
Chat.handle(msg.data);
 
} else {
   
// do something else
 
}
};

namespace 관련해서 Socket.io 구현 코드  확실히 깔끔한 느낌이 있다. 

<script>
 
var chat = io.connect('/chat');
  chat
.on('message', function () {
   
// chat socket messages
 
});
  chat
.on('disconnect', function () {
   
// chat disconnect event
 
});

 
var news = io.connect('/news');
  news
.on('item', function () {
   
// a new `news` socket event is here
 
});
</script>

파라미터 (인코딩/디코딩)도 쉽다.  send 함수에서 emit 을 쓰면 api 의 유용성이 풍부해진다. 

// client-side
var socket = io.connect();
socket
.emit('set nickname', 'john', function (response) {
  console
.log(response);
});

// server-side
// …
socket
.on('set nickname', function (nick, fn) {
 
if (nick == 'rauchg') {
    fn
({ err: 'nickname in use' });
 
}
});

 

Room기능이 추가되었다.
소켓 내에서 room을 구분해서 쓸 수 있게 되었다. 
io.sockets.on('connection', function (socket) {
  socket
.join('a room');
  socket
.broadcast.to('a room').send('im here');
  io
.sockets.in('some other room').emit('hi');
});


역쉬 socket.io 에서 쓰는 이유가 있군.. websocket에 대해서 좀 더 쉽고 깔끔한 코드를 지원한다. 







'scribbling' 카테고리의 다른 글

윈도우 (window) 7 에서 xe + cubrid + xe 1.5.0.8 개발환경 셋팅  (0) 2011.11.04
Socket.io 설치 와 간단 사용  (0) 2011.11.02
websocket #4 (웹소켓의 한계)  (1) 2011.11.02
websocket #3  (0) 2011.10.31
websocket #2 (node.js 설치)  (1) 2011.10.31
websocket #1  (0) 2011.10.28
Posted by 김용환 '김용환'

websocket #3

scribbling 2011.10.31 18:30

아래 스펙을 기준으로 삼아서 공부.
http://www.whatwg.org/specs/web-socket-protocol/

키포인트는 바로 아래 헤더이다. 나머지 secure 한 부분이 있긴 하지만...

Connection : Upgrade
Upgrade:WebSocket


통신은 이렇게 한다. http handshake 하고 나서, 데이터는 시작을 알리는 헤더 0x00 정보 다음와 마지막을 의미하는 0xff 사이에 두어 통신한다. 그리고, 0x00 0xff 는 tcp close를 의미한다. 

내 생각엔  handshake와 통신 주고받는 법, 끊기.. 이게 websocket의 다인것 같다.. 
 

(참조 : http://warmcat.com/_wp/2010/11/01/libwebsockets-html5-websocket-server-library-in-c/)
 


웹 브라우져가 언제든지 소켓처럼 쓸 수 있다. 

(참조 : http://java.sys-con.com/node/1315473)


 


특별히 대단한 기술은 아지만, 다양한 사람들이 모여 하나의 spec를 정하고 이에 맞게 구현하고 있다는 점에서 인정해야 할 것 같다. 생각보다 단순해서 놀랬음.. ^^


참조 : http://cometdaily.com/2008/07/04/html5-websocket/

Orbited is a Web Firewall


 

'scribbling' 카테고리의 다른 글

Socket.io 설치 와 간단 사용  (0) 2011.11.02
websocket #4 (웹소켓의 한계)  (1) 2011.11.02
websocket #3  (0) 2011.10.31
websocket #2 (node.js 설치)  (1) 2011.10.31
websocket #1  (0) 2011.10.28
Comet에 대한 일반론  (0) 2011.10.28
Posted by 김용환 '김용환'
TAG websocket

websocket 요청 하나 만들려고 서버를 무엇을 쓸려고 하나 고민이 된다..
netty, jetty, glassfish, grizzly, node.js 중에. 그냥 node.js로 선택해야 겠다는 생각이 든다..

자바보다는 js~ ㅎㅎ
이번 기회에 node.js도 배울 수 있겠다.


리눅스 OS(ubuntu) 에서 http://nodejs.org/#download 에 접속하고, 가장 최신인 0.4.12를 다운받는다. 


 Download

git repo

2011.09.15 v0.4.12 (stable)

node-v0.4.12.tar.gz Source Code
Documentation




 ./configure 명령을 내린다. 그러나 에러가 난다. 

 ./configure  
Checking for program g++ or c++          : not found 
Checking for program icpc                : not found 
Checking for program c++                 : not found 
/home/google/node-v0.4.12/wscript:232: error: could not configure a cxx compiler!



build-essential 패키지를 설치하니 문제가 사라진다.

sudo aptitude install build-essential 




./configure 명령을 내리면 잘 되는지 확인할 수 있다. 

$ ./configure
Checking for program g++ or c++          : /usr/bin/g++ 
Checking for program cpp                 : /usr/bin/cpp 
Checking for program ar                  : /usr/bin/ar 
Checking for program ranlib              : /usr/bin/ranlib 
Checking for g++                         : ok  
Checking for program gcc or cc           : /usr/bin/gcc 
Checking for program ar                  : /usr/bin/ar 
Checking for program ranlib              : /usr/bin/ranlib 

....
 Checking for header ['sys/types.h', 'sys/event.h'] : not found 
Checking for header sys/queue.h                    : yes 
Checking for function kqueue                       : not found 
Checking for header sys/select.h                   : yes 
Checking for function select                       : yes 
Checking for header sys/eventfd.h                  : yes 
Checking for function eventfd                      : yes 
Checking for SYS_clock_gettime                     : yes 
Checking for library rt                            : yes 
Checking for function clock_gettime                : yes 
Checking for function nanosleep                    : yes 
Checking for function ceil                         : yes 
Checking for fdatasync(2) with c++                 : yes 
'configure' finished successfully (2.194s)



컴파일을 하고, 설치를 완료한다. 

$ make
$ sudo make install



정상적으로 설치 되었는지 확인한다.  node.js 소스 예제(example)을 하나 만든다. 
hello를 표준 출력으로 나오게 하고, 2초 뒤에 world 를 출력한다.  


$ gedit helloworld.js

var sys = require("sys")
sys.puts("hello");
setTimeout(function() {
    sys.puts("world");
}, 2000);


$ node helloword.js 
hello
(2초 뒤) 
world
(종료)

$  



이번엔 tcp 서버 테스트를 진행한다.


터미널 #1
$ gedit helloworld-tcp.js

var tcp = require("net");
 
 tcp.createServer(function(c) {
     c.write("hello world!\n");
    c.end();
 }).listen(8000);


$ node helloworld-tcp.js
(서버)



터미널 #2
$ node helloworld-tcp.js
telnet localhost 8000
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
hello world!
Connection closed by foreign host.



http 서버를 만들어 본다.

node helloworld-http.js

var http = require("http");
     
http.createServer(function(req, res) {
    res.writeHead(200, {"Content-Type": "text/plain"});
    res.write("Hello World!!\r\n");
    res.end();
}).listen(8000);

 $ node helloworld-http.js
(서버)



브라우져로 http://localhost:8000/ 로 접속하면
Hello World!! 가 출력하는 것을 볼 수 있다.


 





마지막으로 시스템 명령어도 내릴 수 있다.


$ gedit system.js

var sys = require("sys"),

spawn = require("child_process").spawn;
 
var ls = spawn("ls", ["-hls", "/"]);
ls.stdout.addListener("data", function(data) {
    sys.print(data);
});


ls -hls  / 의 결과가 출력된다.

$ node system.js 
합계 104K
4.0K drwxr-xr-x   2 root   root   4.0K 2011-10-11 10:30 bin
4.0K drwxr-xr-x   3 root   root   4.0K 2011-10-11 10:31 boot
4.0K drwxr-xr-x   3 root   root   4.0K 2011-10-13 11:35 build
4.0K drwxr-xr-x   2 root   root   4.0K 2011-10-11 10:04 cdrom
4.0K drwxrwxrwx   2 cubrid cubrid 4.0K 2011-10-13 10:35 cubridmanager
   0 drwxr-xr-x  17 root   root   3.6K 2011-10-27 19:17 dev
 12K drwxr-xr-x 138 root   root    12K 2011-10-28 18:20 etc
4.0K drwxr-xr-x   4 root   root   4.0K 2011-10-25 11:05 home
   0 lrwxrwxrwx   1 root   root     33 2011-10-11 10:31 initrd.img -> boot/initrd.img-2.6.32-34-generic
   0 lrwxrwxrwx   1 root   root     33 2011-10-11 10:06 initrd.img.old -> boot/initrd.img-2.6.32-28-generic
 12K drwxr-xr-x  20 root   root    12K 2011-10-11 10:30 lib
 16K drwx------   2 root   root    16K 2011-10-11 10:01 lost+found
4.0K drwxr-xr-x   4 root   root   4.0K 2011-10-27 10:08 media
4.0K drwxr-xr-x   2 root   root   4.0K 2010-04-23 19:11 mnt
4.0K drwxr-xr-x   5 root   root   4.0K 2011-10-13 10:35 opt
   0 dr-xr-xr-x 182 root   root      0 2011-10-27 10:07 proc
4.0K drwx------  12 root   root   4.0K 2011-10-28 18:48 root
4.0K drwxr-xr-x   2 root   root   4.0K 2011-10-11 10:37 sbin
4.0K drwxr-xr-x   2 root   root   4.0K 2009-12-06 06:55 selinux
4.0K drwxr-xr-x   2 root   root   4.0K 2011-02-11 22:04 srv
   0 drwxr-xr-x  12 root   root      0 2011-10-27 10:07 sys
4.0K drwxrwxrwt  15 root   root   4.0K 2011-10-28 19:04 tmp
4.0K drwxr-xr-x  11 root   root   4.0K 2011-10-11 15:05 usr
4.0K drwxr-xr-x  16 root   root   4.0K 2011-10-11 12:05 var
   0 lrwxrwxrwx   1 root   root     30 2011-10-11 10:31 vmlinuz -> boot/vmlinuz-2.6.32-34-generic
   0 lrwxrwxrwx   1 root   root     30 2011-10-11 10:06 vmlinuz.old -> boot/vmlinuz-2.6.32-28-generic




websocket을 테스트해본다.


서버 코드
간단하게 테스트할려고. socket.io를 설치 없이 node.js 단에서 한 테스트.. 


websocket.js

var sys = require('sys'), ws = require('./ws');

ws.createServer(function (socket) {
socket.addListener("connect", function (resource) {
      sys.debug("connect: " + resource);
//socket.write("welcome WebSocket Server\r\n");
setTimeout(socket.end, 100 * 1000); 

}).addListener("data", function (data) {
console.info("read data: " + data);
//socket.write(data);

}).addListener("close", function () {
sys.puts("client left");
})

}).listen(8000);


 
ws.js  (https://github.com/ncr/node.ws.js 에서 조금 수정한 버전) 
이 내용을 잘 살피면서 websocket handshake에 대한 감을 잡을 수 있었음..

 // Github: http://github.com/ncr/node.ws.js
// Compatible with node v0.1.91
// Author: Jacek Becela
// Contributors:
//   Michael Stillwell  http://github.com/ithinkihaveacat
//   Nick Chapman       http://github.com/nchapman
//   Dmitriy Shalashov  http://github.com/skaurus
//   Johan Dahlberg
//   Andreas Kompanez
//   Samuel Cyprian http://github.com/samcyp
// License: MIT
// Based on: http://github.com/Guille/node.websocket.js

function nano(template, data) {
  return template.replace(/\{([\w\.]*)}/g, function (str, key) {
    var keys = key.split("."), value = data[keys.shift()];
    keys.forEach(function (key) { value = value[key];});
    return value;
  });
}

function pack(num) {
  var result = '';
  result += String.fromCharCode(num >> 24 & 0xFF);
  result += String.fromCharCode(num >> 16 & 0xFF);
  result += String.fromCharCode(num >> 8 & 0xFF);
  result += String.fromCharCode(num & 0xFF);
  return result;
}

var sys  = require("sys"),
  net    = require("net"),
  crypto = require("crypto"),
  requiredHeaders = {
    'get': /^GET (\/[^\s]*)/,
    'upgrade': /^websocket$/,
    'connection': /^Upgrade$/,
    'host': /^(.+)$/,
    'origin': /^(.+)$/
  },
  handshakeTemplate75 = [
    'HTTP/1.1 101 Web Socket Protocol Handshake', 
    'Upgrade: websocket', 
    'Connection: Upgrade',
    'WebSocket-Origin: {origin}',
    'WebSocket-Location: {protocol}://{host}{resource}',
    '',
    ''
  ].join("\r\n"),
  handshakeTemplate76 = [
    'HTTP/1.1 101 WebSocket Protocol Handshake', // note a diff here
    'Upgrade: websocket',
    'Connection: Upgrade',
    'Sec-WebSocket-Origin: {origin}',
    'Sec-WebSocket-Location: {protocol}://{host}{resource}',
    '',
    '{data}'
  ].join("\r\n"),
  flashPolicy = '<cross-domain-policy><allow-access-from domain="*" to-ports="*" /></cross-domain-policy>';



exports.createSecureServer = function (websocketListener, credentials, options) {
if (!options) options = {};
options.secure = credentials;
return this.createServer(websocketListener, options);
};

exports.createServer = function (websocketListener, options) {
  if (!options) options = {};
  if (!options.flashPolicy) options.flashPolicy = flashPolicy;
  // The value should be a crypto credentials
  if (!options.secure) options.secure = null;

  return net.createServer(function (socket) {
//Secure WebSockets
var wsProtocol = 'ws';
if(options.secure) {
 wsProtocol = 'wss';
 socket.setSecure(options.secure);
}

console.info("1");

    socket.setTimeout(0);
    socket.setNoDelay(true);
    socket.setKeepAlive(true, 0);

console.info("2");

    var emitter = new process.EventEmitter(),
      handshaked = false,
      buffer = "";
      
console.info("3");
    function handle(data) {
      buffer += data;
      
console.info("4");
      var chunks = buffer.split("\ufffd"),
        count = chunks.length - 1; // last is "" or a partial packet
        
console.info("5");
      for(var i = 0; i < count; i++) {
        var chunk = chunks[i];
        if(chunk[0] == "\u0000") {
console.info("6");
          emitter.emit("data", chunk.slice(1));
        } else {
console.info("7");
          socket.end();
          return;
        }
      }
      

      buffer = chunks[count];
console.info("6");
    }

    function handshake(data) {
console.info("handshake");
      var _headers = data.split("\r\n");

      if ( /<policy-file-request.*>/.exec(_headers[0]) ) {
        socket.write( options.flashPolicy );
        socket.end();
console.info("handshake-1");
        return;
      }

      // go to more convenient hash form
      var headers = {}, upgradeHead, len = _headers.length;
      if ( _headers[0].match(/^GET /) ) {
        headers["get"] = _headers[0];
      } else {
console.info("handshake-2");
        socket.end();
        return;
      }

console.info("handshake-3");
      if ( _headers[ _headers.length - 1 ] ) {
        upgradeHead = _headers[ _headers.length - 1 ];
        len--;
      }
      while (--len) { // _headers[0] will be skipped
        var header = _headers[len];
        if (!header) continue;

        var split = header.split(": ", 2); // second parameter actually seems to not work in node
        headers[ split[0].toLowerCase() ] = split[1];
      }
console.info("handshake-4");

      // check if we have all needed headers and fetch data from them
      var data = {}, match;
      for (var header in requiredHeaders) {



        //           regexp                          actual header value
// modified
console.info("handshake-5 header param - [" + header + "] : " + headers[header] );

        if ( match = requiredHeaders[ header ].exec( headers[header] ) ) {
          data[header] = match;
        } else {
console.info("handshake-5 end.. requiredHeader");
          socket.end();
          return;
        }
      }

console.info("handshake-6");

      // draft auto-sensing
      if ( headers["sec-websocket-key1"] && headers["sec-websocket-key2"] && upgradeHead ) { // 76
console.info("handshake-7");
        var strkey1 = headers["sec-websocket-key1"]
          , strkey2 = headers["sec-websocket-key2"]

          , numkey1 = parseInt(strkey1.replace(/[^\d]/g, ""), 10)
          , numkey2 = parseInt(strkey2.replace(/[^\d]/g, ""), 10)

          , spaces1 = strkey1.replace(/[^\ ]/g, "").length
          , spaces2 = strkey2.replace(/[^\ ]/g, "").length;

        if (spaces1 == 0 || spaces2 == 0 || numkey1 % spaces1 != 0 || numkey2 % spaces2 != 0) {
console.info("handshake-7 end");
          socket.end();
          return;
        }

        var hash = crypto.createHash("md5")
        , key1 = pack(parseInt(numkey1/spaces1))
        , key2 = pack(parseInt(numkey2/spaces2));
        
        hash.update(key1);
        hash.update(key2);
        hash.update(upgradeHead);

        socket.write(nano(handshakeTemplate76, {
          protocol: wsProtocol,
// modified
          resource: data.get[1],
          host:     data.host[1],
          origin:   data.origin[1],
          data:     hash.digest("binary")
        }), "binary");

      } else { // 75
console.info("handshake-8");
        socket.write(nano(handshakeTemplate75, {
          protocol: wsProtocol,
//modified
          resource: data.get[1],
          host:     data.host[1],
          origin:   data.origin[1]
        }));

      }

      handshaked = true;
      emitter.emit("connect", data.get[1]);
console.info("handshake-9");
    }

    socket.addListener("data", function (data) {
      if(handshaked) {
        handle(data.toString("utf8"));
      } else {
        handshake(data.toString("binary")); // because of draft76 handshakes
                }
    }).addListener("end", function () {
console.info("handshake-9 end..");
      socket.end();
    }).addListener("close", function () {
      if (handshaked) { // don't emit close from policy-requests
        emitter.emit("close");
      }
    }).addListener("error", function (exception) {
      if (emitter.listeners("error").length > 0) {
        emitter.emit("error", exception);
      } else {
console.info("exception");
        throw exception;
                }
    });


   console.info("9");
    emitter.remoteAddress = socket.remoteAddress;
    
    emitter.write = function (data) {
      try {
        socket.write('\u00', 'binary');
        socket.write(data, 'utf8');
        socket.write('\uff', 'binary');
      } catch(e) { 
   console.info("socket error -9");
        // Socket not open for writing, 
        // should get "close" event just before.
        socket.end();
      }
    };
    
   console.info("10");
    emitter.end = function () {
 console.info("emitter.end");
      socket.end();
    };
    
    websocketListener(emitter); // emits: "connect", "data", "close", provides: write(data), end()
  });
};





8000번 포트로 접속하고  아래 http 명령어를 날려봄

 GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com:8080
Origin: http://www.example.com 

정상적으로 잘 나온다. 

$ telnet localhost 8000
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: example.com:8080
Origin: http://www.example.comHTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: websocket
Connection: Upgrade
WebSocket-Origin: undefined
WebSocket-Location: ws://example.com:8080/

(커넥션 연결된 상태)




클라이언트 (브라주져. ws.html) 코드


<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">

function WebSocketTest() {

  if ("WebSocket" in window) {

     alert("WebSocket is supported by your Browser!");
     
     var socket = new WebSocket("ws://localhost:8000");

     socket.onopen = function() {
        //ws.send("hello world");
        alert("Message is sent...");
            };



     socket.onmessage = function (evt) { 
        var received_msg = evt.data;
        alert("Message is received..." + received_msg);
            };

socket.onerror = function (error) {
  alert("error.." + error);
};


     socket.onclose = function() { 
        alert("Connection is closed..."); 
           };



 } else {
     alert("WebSocket NOT supported by your Browser!");
   }
}


</script>
</head>
<body>
<div id="sse">
   <a href="javascript:WebSocketTest()">Run WebSocket1</a>
</div>

</body>
</html>



내가 가지고 있는 크롬 웹 브라우져에서는 connection을 맺자마자 바로 fin 패킷을 보내면서 connection을 종료한다. 어딘가 약간 잘못된 것 같기는 하지만, 데모용으로만 쓸 거라서, 문제 원인을 자세히 파악하는 것은 패쓰.. 맛만 봤다는 점에서 통과해야겠음.

와이어샤크 정보





다음에는 websocket 원리를 봐야지..








<부록>

node.js를 사용한 이유는 머 간단하 websocket 테스트하려고 한것 이었는데. 쓰면서 문제점들이 좀 발견되었다. 

* node.js 의 문제점 

#1. 버그 하나로 시스템에 영향을 줄 수 있음

아래 코드에서 response 객체에 대한 end() function이 호출되지 않았을 때, 치명적으로 문제가 생긴다.
하나의 요청에서 end가 안되었기 때문에 모든 요청은 blocking된 요청이 끝나기를 기다려야 한다. 
버그 하나에 치명적임..

var http = require("http");
     
http.createServer(function(req, res) {
    res.writeHead(200, {"Content-Type": "text/plain"});
    res.write("Hello World\r\n");

    //res.end();
}).listen(8000);




#2 피보나치 이슈 (node.js에 재귀적 메소드에 문제가 있는 것 같다. )

 
재귀적 함수(피보나치)에 대해서 속도 이슈가 있다. 

var http = require("http");

http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end(fibonacci(30).toString());
}).listen(8000);

function fibonacci(n) {
  if (n < 2)
    return 1;
  else
    return fibonacci(n-2) + fibonacci(n-1);
}



결과값은 아래과 같이 확인한다. 

$ time curl http://localhost:8000



10에 대한 피보나치 수열의 값을 구했을때는 0.007초가 걸린다. 
  res.end(fibonacci(10).toString());

$ time curl http://localhost:8000
10946
real 0m0.007s
user 0m0.000s
sys 0m0.004s




30에 대한 피보나치 수열의 값을 구했을때는 0.053초가 걸린다. 
  res.end(fibonacci(30).toString());

 $ time curl http://localhost:8000
1346269
real 0m0.053s
user 0m0.004s
sys 0m0.000s



아래와 같이 40의 피보나치 수열의 값을 구했을때는 4초 이상이 걸린다. 

  res.end(fibonacci(40).toString());
 

$ time curl http://localhost:8000
165580141
real 0m4.312s
user 0m0.008s
sys 0m0.000s



100의 피보나치 수열의 값을 구할때는 상상을 초월한다. 

  res.end(fibonacci(100).toString());
 

$ time curl http://localhost:8000

30분동안 아무런 응답이 없어서, 그냥 종료시켰다. 



cpu는 최대한 활용하고 있다. 엔진의 이슈일까?? 



 #3. 코드 관리
자바스크립트 특성상, 코드 관리를 잘 해야 한다. BO가 들어가는 순간부터 복잡해질 것 같다. ...
















'scribbling' 카테고리의 다른 글

websocket #4 (웹소켓의 한계)  (1) 2011.11.02
websocket #3  (0) 2011.10.31
websocket #2 (node.js 설치)  (1) 2011.10.31
websocket #1  (0) 2011.10.28
Comet에 대한 일반론  (0) 2011.10.28
글쓰기 전략  (0) 2011.10.27
Posted by 김용환 '김용환'
TAG websocket

websocket #1

scribbling 2011.10.28 18:40

이미 long polling이 대세인 상태에서, WebSocket이 앞으로 대세가 될지는 모르겠다.
수많은 웹 게임은 short polling 으로, 일부 웹 게임 또는 웹채팅은 long polling으로, flashsocket을 이용한 streaming 방식을 websocket이 대체하기는 많은 시간이 흘러야 하지 않을까?

websocket을 브라우져에서 지원하는 현황(http://caniuse.com/#search=socket)을 보더라도 당장 쓰기가 쉽지 않다. 


  
그렇다하다도, 미리 공부해도 준비하는 것도 나쁘지 않다. tcp도 보편화될때까지 많은 시간이 걸리지 않았는가? 새롭고 좋은 것들은 계속 나와도 무방하다. ㅎ

하여튼, 이런 복잡한 대안안에서 프레임워크 형태인  socket.io를 찾는 것 같다.
socket.io는 node.js의 하나의 모듈로서, websocket 뿐 아니라, flashsocket, long polling, streaming, jsonp polling을 잘 추상화하였다.

http://socket.io/ 홈페이지에 있듯이, 서버는 단순하게 80포트를 열고 socket.io만 읽으면 되며, 클라이언트는 간단하게 접속하면 되는 스크립트 프레임워크이다. 


서버 
 var io = require('socket.io').listen(80);
io.sockets.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('my other event', function (data) {
    console.log(data);
  });
});


클라이언트
<script src="/socket.io/socket.io.js"></script>
<script>
  var socket = io.connect('http://localhost');
  socket.on('news', function (data) {
    console.log(data);
    socket.emit('my other event', { my: 'data' });
  });
</script> 


이 녀석은 Internet Explorer 5.5+, Safari 3+, Google Chrome 4+, Firefox 3+, Opera 10.61+,
iPhone Safari, iPad Safari, Android WebKit, WebOs WebKit 등을 지원하기 때문에
아주 현실적인 대안이 된다.

실제로도 서비스에서 많이 사용하고 있다.



인제 차근 차근 websocket에 대해서 공부해봐야지. 이제 시작..
 

'scribbling' 카테고리의 다른 글

websocket #3  (0) 2011.10.31
websocket #2 (node.js 설치)  (1) 2011.10.31
websocket #1  (0) 2011.10.28
Comet에 대한 일반론  (0) 2011.10.28
글쓰기 전략  (0) 2011.10.27
요즘 Nosql 트렌드 (2011년 10)  (0) 2011.10.20
Posted by 김용환 '김용환'
TAG websocket
일본 사람이 만든 websocket, XHR 스트 페이지.
http://komasshu.com/ws/mecab/wakachi.html


pipeline으로 websocket구현 : 112ms
XML Http request : 9,937ms

헉!


Posted by 김용환 '김용환'