Node.js@Windows 導入手順メモ（其の弐 : Socket.IO）

# はじめに

* [前回](http://qiita.com/Thought_Nibbler/items/0b4df832c1629783b7e7)の続き。
* Socket.IO を使えるページを作成することが目標。

# 手順

* 前回で、サーバディレクトリ（アプリ）名を `helloWorld` にしたものとする。
* テンプレートエンジンは `ejs` にしたものとする。


## Socket.IO のインストール

* `helloWorld` ディレクトリで以下を叩く。

```
npm install --save socket.io
```

## View の作成

* 以下のファイルを `helloWorld\views` に作成。

```html:socket.ejs
<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="http://code.jquery.com/jquery-1.11.1.js"></script>
    <script src="/javascripts/client.js"></script>
  </head>
  <body>
    <form action="">
      <input id="m" type="text"/>
      <br />
      <button type="submit">SUBMIT</button>
    </form>
    <hr />
    <ul id="messages"></ul>
  </body>
</html>
```

## ルーティングの追加

* `helloWorld\app.js` を以下のように修正。

```js:app.js
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');
// ここから追加
var socket = require('./routes/socket');
// ここまで追加

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);
// ここから追加
app.use('/socket', socket);
// ここまで追加

// catch 404 and forward to error handler
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


module.exports = app;

```


* 以下のファイルを `helloWorld\routes` に作成。

```js:socket.js
var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('socket', { title: 'socket.io test' });
});

module.exports = router;
```

## ソケット通信処理の実装

* emit() で送れる。
* on() で受け取れる。

### サーバ側

* `helloWorld\bin\www` を以下のように修正。

```js:www
#!/usr/bin/env node
var debug = require('debug')('helloWorld');
var app = require('../app');

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
  debug('Express server listening on port ' + server.address().port);
});

// ここから追加
var io = require('socket.io').listen(server);
io.sockets.on('connection', function (socket) {

  console.log('a user connected');

  socket.on('message', function(msg){
    console.log('message: ' + msg);
    io.emit('message', 'You said "' + msg + '".');
  });

  socket.on('disconnect', function(){
    console.log('user disconnected');
  });

});
// ここまで追加
```

### クライアント側

* `helloWorld\public\javascripts` に以下のファイルを作成。

```js:client.js
$(function () {
    var socket = io();

    $('form').submit(function () {
        socket.emit('message', $('#m').val());
        $('#m').val('');
        return false;
    });

    socket.on('message', function (msg) {
        $('#messages').append($('<li>').text(msg));
    });
});
```

## つないでみよう

```
node .\bin\www
```

* [http://localhost:3000/socket](http://localhost:3000/socket)
* テキストボックスに入力し "SUBMIT" を押すと返事してくれる。

# おわりに

## 感想
* Windows 環境の資料が少なすぎる。

## 今後
導入は終わったので、いろいろ遊ぶ。