node.jsでsoket.ioを使用して簡単なチャットを作成してみた

###まずはsocket.ioモジュールを追加しましょう。

https://www.npmjs.com/package/socket.io

`npm i socket.io`

で追加します。

1.まずはサーバーサイドのコードを書いてみます
説明はコード内のコメントを読んでいただけるとありがたいです。

```javascript:SoketIoServerTest.js
//httpモジュール読み込み
var http = require( 'http' );

// Socket.IOモジュール読み込み
var socketio = require( 'socket.io' );

 // ファイル入出力モジュール読み込み
var fs = require( 'fs' );

//パスのモジュール読み込み
const path = require('path');

//8080番ポートでHTTPサーバーを立てる
var server = http.createServer( function( req, res ) {
  //リクエストされたファイルパスを取り出す
  var filePath = "." + req.url;
  console.log(filePath);

  //ファイルパスのファイル名がなければindex.html
  if (filePath == './') {
      filePath = './index.html'
  }
    
  //拡張子名を取り出す
  var extname = String(path.extname(filePath)).toLowerCase();
  console.log('extenname:' + extname);
    
　//拡張子に対応するコンテンツ表
  var mimeTypes = {
    '.html': 'text/html',
    '.js': 'text/javascript',
    '.css': 'text/css',
    '.json': 'application/json',
    '.png': 'image/png',
    '.jpg': 'image/jpg',
    '.gif': 'image/gif',
    '.wav': 'audio/wav',
    '.mp4': 'video/mp4',
    '.woff': 'application/font-woff',
    '.ttf': 'application/font-ttf',
    '.eot': 'application/vnd.ms-fontobject',
    '.otf': 'application/font-otf',
    '.svg': 'application/image/svg+xml',
    '.ico': 'image/x-icon'
};
    
　//MIMEがない場合はデフォルトを使用
　var contentType = mimeTypes[extname] || 'application/octet-stream';
　
  
  //リクエストされたファイルパスを読み込み
  fs.readFile(filePath, function(error, content) {

    //エラー処理
    if (error) {
      console.log('ERROR!!' + error.code);
        //リクエストしたファイルが存在しない場合
        if (error.code === 'ENOENT') {
          //ファイルパスの先にファイルがないエラー
          res.writeHead(404);
          res.write('Sorry, check with the site admin for error: '+error.code+' ..\n404');
          res.end();
            
      } else {
        //CGIエラー
        res.writeHead(500);
        res.write('Sorry, check with the site admin for error: '+error.code+' ..\n500');
        res.end();
      }
    } else {
      //エラーがない場合、正常処理
      res.writeHead(200, { 'Content-Type': contentType });
      res.end(content, 'utf-8');


    }
  });
    
    

}).listen(8080);

//サーバーをソケットに紐づける
var io = socketio.listen( server );

//接続確立後の通信処理部分を定義
io.sockets.on( 'connection', function( socket ){
  var name;
  console.log('コネクション:' + socket);

  //クライアントからサーバーへメッセーゾ送信ハンドラ(自分を含む全員に送る)
   socket.on( 'c2s_message', function( data ) {

//サーバーからクライアントへメッセージ送り返し
  io.sockets.emit( 's2c_message', { value : data.value } );
  console.log('通常メッセージ:' + data.value);

});

  //サーバーからクライアントへメッセージ送信ハンドラ(自分以外の全員に送る)
  socket.on( 'c2s_broadcast', function( data )  {

    //サーバーからクライアントへメッセージ送り返し
    socket.broadcast.emit( 's2c_message', { value : data.value } );
    console.log('ブロードキャストメッセージ:' + data.value);

  });

  socket.on('c2s_personal', function( data ){

    var id = socket.id;
    name = data.value;
    var personalMessage = 'あなたは、' + name + 'さんとして入室しました。';
    console.log('ゆーざーID:' + id);

    io.to(id).emit('s2c_message',{ value: personalMessage });

  });
});
```


2.次はクライアント側のjavascriptを書いてみます
こちらも説明はコード内のコメントを読んでいただけると幸いです。
ちなみにjQueryを使用しています。index.htmlの方で読み込んでおいてくださいね。

```javascript:js/clienttest.js
//空のioSocket用意
var ioSocket = { on: function(){}};

function connect() {
  if(!ioSocket.connected){
//サーバーへ接続
ioSocket = io.connect('http://' + window.location.host);
console.log('URL:' + window.location.host);
console.log('サーバー接続!!');
} else {
  //サーバーへ再接続
  ioSocket.connect();
  console.log('サーバー再接続!!')
}
}

connect();

//サーバーからの受け取り処理
ioSocket.on('connect',function(){});
ioSocket.on('disconnect',function(){});

var isEnter = false;
var userName;

//サーバーからの送り返し
ioSocket.on('s2c_message',function( data ){ appendMessage( data.value ) });

//画面にメッセージを描画
function appendMessage( text ) {
  $('#messageView').append('<div>' + text + '</div><br/>');
    console.log("メッセージ:" + text);
}


//自分を含む全員宛てにメッセージを送信
$('#sendMessageBtn').on('click',function(){
  //メッセージの内容を取得し、フォームをレフレッシュ
  var message = $('#messageForm').val();
  $('#messageForm').val('');

  //入室処理
  if (isEnter) {
    message = '[' + userName + '] ' + message;
  //クライアントからサーバーへ送信
  ioSocket.emit('c2s_message',{ value: message });
} else {
  userName = message;
  var entryMessage = userName + 'さんが入室しました。';
  ioSocket.emit('c2s_broadcast',{ value: entryMessage });


  ioSocket.emit('c2s_personal' ,{ value: userName });
  changeLabel();
}
});

function changeLabel() {
  $('input').attr('placeholder','message In');
  $('button').text('送信');
  isEnter = true;
}

$(window).on("beforeunload",function() {
        var getoutMessage = userName + 'さんが退室しました。';
        ioSocket.emit('c2s_broadcast',{ value: getoutMessage});
        ioSocket.disconnect();
    });
```

3.簡単なhtmlを作成します。

```html:index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
    <script type="text/javascript" src="./lib/jquery-3.4.1.min.js"></script>
    <script type="text/javascript" src="node_modules/socket.io-client/dist/socket.io.js"></script>
</head>
<body>
    <style>
    #messageForm {
        margin-top: 15px;
    }
    </style>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<div class="form-group">
<input type="text" class="form-control" id="messageForm" placeholder="name In" />
<button class="btn btn-primary" id="sendMessageBtn">入室</button>

</div>
<div id="messageView"></div>
</div>
</div>
</div>

<script type="text/javascript" src="js/clienttest.js"></script>

</body>
</html>
```

では、ターミナルを開いて
`node サーバーファイル名`

で起動してからブラウザで
http://localhost:8080/
にアクセスしてみましょう。

##このような動作になるかと思います。

![スクリーンショット 2020-04-19 16.00.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598005/b429c0df-6a77-3ec8-1ab7-50676fa93961.png)

ブラウザの別タグでログインしてメッセージを送信してみます。

![スクリーンショット 2020-04-19 16.05.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598005/3f6d1ba7-5788-118a-6807-b6109b0cc2ed.png)

メッセージが来ました！！さらに同一Lan内であればスマートフォンでチャットも出来ます。送信してみます。

![Screenshot_20200419-160842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598005/4ccf36e3-ddaf-48ce-1eb2-529ba22ce868.png)

届きました！！

![スクリーンショット 2020-04-19 16.13.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598005/14695d6d-30d0-84fe-66ba-55fe6812d224.png)

以上で終わりですが動きがあるのは楽しいですね。

余談ですが
JavaとjavascriptでWebSocketを試してみよう！
https://qiita.com/keisuke1112/items/5c989eb8f0e868a25435

私の別記事でjavaとjavascriptでwebsocketを使用してみたのですが、node.jsの方が手軽に書けるような気がします。