Help us understand the problem. What is going on with this article?

Socket.ioを使ったチャットルーム ロジックの実装

More than 3 years have passed since last update.

Node.jsの勉強がてら地図上でお話しできるチャットアプリを作成していたら、チャットルームの管理が面倒なので、FacebookのMessengerで管理しているグループと連動できないかと思ってやってみた雑記です。
FacebookメッセンジャーのConversation IDを利用してチャットルームUIを作るの続編。

チャットルーム ロジック実装

socket.ioのRoomsを使ったチャットルームの作り方

チャットルームはSocket.ioのRoomsを使って実現します。RoomsはSocketのチャンネルであり、一度Roomsでチャンネルを初期化してしまえば、Socket.ioでチャンネルごとに送信先を分けることができます。

  • socket.io: Rooms

http://socket.io/docs/rooms-and-namespaces/#rooms

io.js(Room実装前)

io.js
    var socketio = require('socket.io');

    function io(server) {
      var io = socketio.listen(server);

      io.on('connection', function (socket) {
        socket.on('chat message', function(msg) {
          io.emit('chat message', msg);
        });
        socket.on('map message', function(msg) {
          io.emit('map message', msg);
        });
      });
    }
    module.exports = io;

上記コード内に以下のコードを追加してRoomを初期化。

socket.join('<Room ID>');

メッセージ配信時に特定のRoomにのみ配信を行うためにRoom ID指定したioでemitする。

io.to('<Room ID>').emit('chat message', msg);

これだけ。
以下、Room実装後のio.js。function io内抜粋。

io.js(Room実装後)

io.js
    var io = socketio.listen(server);

    var store = {};

    io.on('connection', function (socket) {
      socket.on('join', function(msg) {
        usrobj = {
          'room': msg.roomid,
          'name': msg.name
        };
        store[msg.id] = usrobj;
        socket.join(msg.roomid);
      });

      socket.on('chat message', function(msg) {
        io.to(store[msg.id].room).emit('chat message', msg);
      });
      socket.on('map message', function(msg) {
        io.to(store[msg.id].room).emit('map message', msg);
      });
    });

この後はおまけです。

チャットルームを永続的に残さない、かつユーザー1人に対して参加できるチャットルームを1ルームのみとして、FacebookのMessengerで管理されているグループと同期してチャットルームを生成する仕組みです。

チャットルームUI実装で取得したFacebookのConversation IDをRoom IDに使用して実装

ルームに入る際にルーム初期化のための送信メッセージ('join')をemitする。
roomidにConversation IDが入ります。
Conversation IDの取得はFacebookメッセンジャーのConversation IDを利用してチャットルームUIを作るを参考にしてください。

view/index.ejs
          socket.emit('join', {
            roomid: e.target.id,
            name: myname,
            id: myid
          });

socket.on('join')で渡されたmsg.idにはFacebookのConversation IDが入ってるので、これをRoom IDとしてsocket.joinする。

io.js
    socket.join(msg.roomid);

これにより、RoomはFacebookのメッセンジャーグループと同期される。

連想配列(store = {})を作って、そこに接続ユーザーの情報を格納して、emitする際にstoreからRoom IDを取得して利用する。

io.js
    io.to(store[msg.id].room).emit('chat message', msg);

退出の実装

最後に、Socket切断時の自動退出の実装です。

socket.idとFacebookユーザーIDを紐付けて管理します。

io.js
    var idstore = {};

    // JOIN時に格納
    idstore[socket.id] = { 'id': msg.id };

Webアプリなのでセッションが切れると接続も切れる。
(※今回は明示的に切断するためのUIは作ってない)

Socketのdisconnect時にidstore[socket.id].idで退出したユーザーを確定する。退出メッセージ送信後は不要なidstoreを削除。

io.js
      socket.on('disconnect', function() {
        if (idstore[socket.id]) {
          var _roomid = store[idstore[socket.id].id].room;
          socket.leave(_roomid);
          io.to(_roomid).emit('chat message', {
            id: idstore[socket.id].id,
            name: store[idstore[socket.id].id].name,
            text: '退出!'
          });
          delete idstore[socket.id];
        }
      });

メモ:if (idstore[socket.id])内で実行するようにしておかないとサーバー側のエラーが出てHerokuで動作させているアプリがエラーで使えなくなった。ログを見てると切断後ポーリングをして接続状況を確認してるのか、再度disconnectが発行されて処理に失敗してる感じ。

以上です。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした