socket.io创建聊天室

首先贴一下目录结构

其中server.js是负责server.js 负责文件读取、创建server等功能,并且引入socket.io服务,允许它搭载在已有的HTTP服务器上。主要处理逻辑是在chat_server.js上,加入聊天室、发送消息、修改名字、切换聊天室等功能。server.js代码如下。

var http = require('http');
var fs = require('fs');
var path = require('path');
var mime = require('mime');
var cache = {};

function send404(response) {
    response.writeHead(404, {'Content-Type': 'text/plain'});
    response.write('Error 404: resource not found');
    response.end();
}
function sendFile(response, filePath, fileContents) {
    response.writeHead(
        200,
        {"content-type": mime.lookup(path.basename(filePath))}
    );
    response.end(fileContents)
}
function serveStatic(response, cache, absPath) {
    if(cache[absPath]) {
        sendFile(response, absPath, cache[absPath])
    } else {
        fs.exists(absPath, function (exists) {
            if (exists) {
                fs.readFile(absPath, function (err, data) {
                    if (err) {
                        send404(response)
                    } else {
                        cache[absPath] = data
                        sendFile(response, absPath, data)
                    }
                })
            } else {
                send404(response)
            }
        })
    }
}
var server = http.createServer(function (request, response) {
    var filePath = false;
    if (request.url == '/' ) {
        filePath = 'public/index.html'
    } else {
        filePath = 'public' + request.url
    }
    var absPath = './' + filePath
    serveStatic(response, cache, absPath)
})
server.listen(3000, function () {
    console.log("server listening on port 3000.")
})
var cheaServer = require('./lib/chat_server');
cheaServer.listen(server)
主要的聊天逻辑处理,是chat_server.js,代码如下

var socketio = require('socket.io');
var io;
var guestNumber = 1;
var nickNames = {};
var namesUsed = [];
var currentRoom = {};
exports.listen = function (server) {
    io = socketio.listen(server)
    io.set('log level', 1);
    io.sockets.on('connection', function (socket) {
        guestNumber = assignGuestName(socket, guestNumber, nickNames, namesUsed)
        joinRoom(socket, 'Lobby')
        handleMessageBroadcasting(socket, nickNames);
        handleNameChangeAttempts(socket, nickNames, namesUsed)
        handleRoomJoining(socket)
        socket.on('rooms', function () {
            socket.emit('rooms', io.sockets.manager.rooms)
        })
        handleClientDisconnection(socket, nickNames, namesUsed)
    })
}

function joinRoom(socket, room) {
    console.log(room)
    socket.join(room)
    currentRoom[socket.id] = room
    socket.emit('joinResult', {room: room})
    socket.broadcast.to(room).emit('message', {
        text: nickNames[socket.id] + 'has joined' + 'room' + '.'
    })

    var usersInRoom = io.of('/').in(room).clients;
    if(usersInRoom.length > 1) {
        var usersInRoomSummary = 'user currently in ' + room + ':'
        for( var index in usersInRoom) {
            var userSocketId = usersInRoom[index].id
            if(userSocketId != socket.id) {
                if(index > 0) {
                    usersInRoomSummary += ', '
                }
                usersInRoomSummary += nickNames[userSocketId]
            }
        }
    }
    usersInRoomSummary += '.'
    socket.emit('message', {text: usersInRoomSummary})
}
function handleNameChangeAttempts(socket, nickNames, namesUsed) {
    socket.on('nameAttempt', function (name) {
        if(name.indexOf('Guest') == 0) {
            socket.emit('nameResult', {
                success: false,
                message: 'names cannet begin with "Guest"'
            })
        } else {
            if (namesUsed.indexOf(name) == -1) {
                var previousName = nickNames[socket.id]
                var previousNameIndex = namesUsed.indexOf(previousName)
                namesUsed.push(name)
                nickNames[socket.id] = name
                delete namesUsed[previousNameIndex]
                socket.emit('nameResult', {
                    success: true,
                    name: name
                })
                socket.broadcast.to(currentRoom[socket.id]).emit('message', {
                    text: previousName + ' is now known as' + name + '.'
                })
            }else {
                socket.emit('nameResult', {
                    success: false,
                    message: 'That name is already in use.'
                })
            }
        }
    })
}
function handleMessageBroadcasting(socket) {
    socket.on('message', function (message) {
        socket.broadcast.to(message.room).emit('message', {
            text: nickNames[socket.id] + ':' + message.text
        })
    })
}
function handleRoomJoining(socket) {
    socket.on('join', function (room) {
        socket.leave(currentRoom[socket.id])
        joinRoom((socket, room.newRoom))
    })
}

function handleClientDisconnection(socket) {
    socket.on('disconnect', function () {
        var nameIndex = namesUsed.indexOf(nickNames[socket.id])
        delete namesUsed[nameIndex]
        delete nickNames[socket.id]
    })
}
function assignGuestName(socket, guestNumber, nickNames, nameUsed) {
    var name = 'Guest' + guestNumber;
    nickNames[socket.id] = name
    socket.emit('nameResult', {
        success: true,
        name: name
    })
    nameUsed.push(name)
    return guestNumber + 1
}

随机浏览