Node.js




ニコニコ事業本部 企画開発部

清水 俊博

自己紹介

氏名

所属

SocialMedia

アジェンダ

Node.jsの紹介

Node.jsとは何か

サーバサイドJavaScript

解決すべき問題

どうやって解決したか

イベントループモデル

問題点

種別サイクルメートル換算
CPU L1キャッシュ33m
CPU L2キャッシュ1414m
メモリ250250m
ディスク41,000,000地球1周
ネットワーク240,000,000地球6周

ノンブロッキングI/O

このようなプラットフォームをどの言語向けに提供すべきか

JavaScript

JavaScriptにした恩恵

Node.jsを使う

適した分野

作るもの

使うもの

Node.jsは低レベルのAPIしか用意していないので、このようなモジュールを使って開発するのが一般的

インストール

$ curl http://nodejs.org/dist/node-v0.4.10.tar.gz | tar xz
$ cd node-v0.4.10
$ ./configure
$ make
$ sudo make install
$ curl http://npmjs.org/install.sh | sudo sh
      

準備

$ npm install express -g
$ express chat
$ cd chat
$ cat package.json
{
    "name": "ChatSample"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.4.3"
    , "jade": ">= 0.0.1"
    , "socket.io": ">= 0.7"
  }
}
$ npm install
      

ディレクトリ構成

chat
  - public
      - stylesheets
          - style.css
      - images
      - javascripts
  - views
      - layout.jade
      - index.jade
  - app.js
  - package.json
  - node_modules
      - express
      - socket.io
      

app.js

var express = require('express');
var app = module.exports = express.createServer();

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});
      

app.js続き

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); 
});
app.configure('production', function(){
  app.use(express.errorHandler()); 
});
app.get('/', function(req, res){
  res.render('index', {
    title: 'Express'
  });
});
app.listen(3000);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
      

view/index.jade

h1= title
p Welcome to #{title}
      

view/layout.jade

!!!
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body!= body
      

実行

$ node app.js
      

http://localhost:3000/

リアルタイムアプリケーションの実装

  1. 同時アクセス数を表示 ←まずここ
  2. チャットテキストの送受信

Socket.IO - サーバ側

var io = require('socket.io').listen(app);
var chatCount = 0;
var messages = []; // あとで使う
var chat = io.of('/chat').on('connection', function(socket) {
  chatCount++;
  chat.emit('count', {count: chatCount});

  socket.on('message', function(data) {
    // ブラウザからチャットテキストを受信した時の処理
  });
  socket.on('disconnect', function() {
    chatCount--;
    chat.emit('count', {count: chatCount});
  });
});
     

Socket.IO - ブラウザ側

var chat = io.connect('http://localhost:3000/chat');
chat.on('connect', function() {
  chat.on('count', function(data) {
    $('#count').text(data.count);
  });
  chat.on('message', function(data) {
    // サーバからチャットテキストを受信した時の処理
  });
});
function send() {
  // サーバへチャットテキストを送信する処理
}
      

テンプレート

h1= title
p 現在接続している人は
  span#count
  人います
#chat
form#form(onsubmit='send(); return false;')
  input#name(type='text', placeholder='Name')
  input#text(type='text', autocomplete='off')
  input(type='submit', value='送信')
      

リアルタイムアプリケーションの実装

  1. 同時アクセス数を表示
  2. チャットテキストの送受信 ←次ここ

サーバへ送信する処理

function send() {
  var name = $('#name').val();
  var text = $('#text').val();
  if (text && name) {
    chat.emit('message', {name: name, text: text});
    $('#text').val('');
  }
}
      

サーバが受信したときの処理

var chat = io.of('/chat').on('connection', function(socket) {
  //省略(count++の処理)
  messages.forEach(function(data) {
    socket.emit('message', data);
  });
  socket.on('message', function(data) {
    data.timestamp = new Date().getTime();
    chat.emit('message', data);
    var length = messages.push(data);
    if (length > 100) {
      messages.shift();
    }
  });
  //省略(切断時のcount--の処理)
});
      

ブラウザ受信時の処理

chat.on('message', function(data) {
  var date = new Date(data.timestamp);
  $('#chat').append(
    '<div class="chatlog"><p>
    + escape(data.name)
    + ': '
    + escape(data.text)
    + '</p><span class="date">'
    + date.toString()
    + '</span></div>');
  $('#chat').scrollTop(1000000);
});
      

完成したチャット

http://miyukki.mesolabs.com/chat

ソースコード

http://github.com/meso/miyukki

まとめ

ありがとう

ございました


http://miyukki.mesolabs.com/

0 / 0

閲覧者数: 0