2019/03/09

使用Node.js和Redis建立一個HTML5聊天室

這篇程式碼主要由IBM Developerworks所提供
我建置的專案如下圖

這篇想法就是透過WebSocket來建立通訊
將接收到的值以JSON方式存進Redis的list內
並透過Broadcast filter到的訊息將其加入至聊天室內

app.js

var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var app = express();


// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;


www.js


#!/usr/bin/env node

var app = require('../app');
var http = require('http').Server(app);
var io = require('socket.io')(http);
var redis = require('redis');
const redisClient = redis.createClient(6379, '192.168.126.128');

io.on('connection', function(socket) {
    socket.on('msg', function(data) {
        socket.broadcast.emit('msg', data);
        redisClient.lpush('messages', JSON.stringify(data));
        redisClient.ltrim('messages', 0, 99);
    });
    socket.on('join', function(nickname) {
        socket.nickname = nickname;
        socket.broadcast.emit('notice', nickname + ' has joined the chat.');
    });
    socket.on('disconnect', function() {
        socket.broadcast.emit('notice', socket.nickname + ' has left the chat.');
    });
});


http.listen(3000);


client.js

$(document).ready(function() {
    var socket = io(), nickname, msgList = $('#messages');

    if('localStorage' in window && localStorage.getItem('name')) {
        nickname = localStorage.getItem('name');
    } else {
        nickname = prompt('input your nickname');
        if('localStorage' in window) {
            localStorage.setItem('name', nickname);
        }
    }
    socket.emit('join', nickname);

    var newMessage = function(data) {
        var who = $('<div class="who">').text(data.nickname),
            when = $('<div class="when">').text(new Date().toString().substr(0, 24)),
            msg = $('<div class="msg">').text(data.msg),
            header = $('<div class="header clearfix">').append(who).append(when),
            li = $('<li>').append(header).append(msg);

        msgList.prepend(li);
    };

    $('form').submit(function(e) {
        var msgField = $('#msg'),
            data = { msg: msgField.val(), nickname: nickname, when: new Date() };
        e.preventDefault();
        socket.emit('msg', data);
        newMessage(data);
        msgField.val('');
    });

    socket.on('msg', function(data) {
        newMessage(data);
    });

    socket.on('notice', function(msg) {
        msgList.prepend($('<div class="notice">').text(msg));
    });

});

index.pug

extends layout

block content
  h1=title
  form
    input(id='msg' type='text' autocomplete='off' autofocus)
    button(type='submit') send
  ul#messages
  - for(var i=0,ln =messages.length;i<ln;i++)
    li
    .header.clearfix
    .who= messages[i].nickname
    .when= new Date(messages[i].when).toString().substr(0, 24)
    .msg= messages[i].msg


參考資料:
http://zh.wikipedia.org/wiki/WebSocket
http://usherchen.blogspot.tw/2013/07/html-websocket-sample-with-php-server.html
http://kheresy.wordpress.com/2013/04/02/html5-websocket-client/
https://developer.mozilla.org/zh-TW/docs/WebSockets/Writing_WebSocket_client_applications
http://blog.mukispace.com/websocket-simple-introduce-and-use/
http://www.mrdoob.com/projects/multiuserpad/
http://www.websocket.org/echo.html
http://msdn.microsoft.com/zh-tw/library/ie/hh673567(v=vs.85).aspx
http://dev.w3.org/html5/websockets/
http://dev.w3.org/html5/websockets/#ping-and-pong-frames
http://dev.w3.org/html5/websockets/#feedback-from-the-protocol
https://www.ibm.com/developerworks/cn/web/wa-bluemix-html5chat/index.html