NodeJs 实战-构建有多个房间的聊天室

版本信息

C:\Users\Administrator>node -v
v18.12.1

C:\Users\Administrator>npm -v
8.19.3

聊天室页面展示

首页

在这里插入图片描述

修改昵称

输入 /nick chengdu
在这里插入图片描述

切换房间

点击右侧房间列表切换
在这里插入图片描述

基础知识文档

nodejs web

使用node 启动一个 web服务

const http = require('http')

const hostname = '127.0.0.1'
const port = 3000

const server = http.createServer((req, res) => {
    
    
	res.statusCode = 200
	res.setHeader('Content-Type', 'text/plain')
	res.end('Hello World\n')
})

server.listen(port, hostname, () => {
    
    
	console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

socket 文档地址

https://socket.io/

主要代码

server.js

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

const hostname = '127.0.0.1';
const port = 3000;

/**
 * 请求不存在时,发送404错误
 * @param {*} response 
 */
function send404(response) {
    
    
    response.writeHead(404, {
    
    'Content-Type': 'text/plain'});
    response.write('Error 404: resource not found.');
    response.end();
}

/**
 * 发送文件
 * @param {*} response 
 * @param {*} filePath 
 * @param {*} fileContents 
 */
function sendFile(response, filePath, fileContents) {
    
    
    response.writeHead(200, 
        {
    
    "Content-type": mime.lookup(path.basename(filePath))}
    );
    response.end(fileContents);
}

/**
 * 静态资源查找
 * @param {*} response 
 * @param {*} cache 
 * @param {*} absPath 
 */
function serverStatic(response, cache, absPath) {
    
    
    if (cache[absPath]) {
    
    
        sendFile(response, absPath, cache[absPath]);
    } else {
    
    
        if (fs.existsSync(absPath)) {
    
    
            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;
    serverStatic(response, cache, absPath);
});

server.listen(port, hostname, () => {
    
    
	console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
});

var chatServer = require('./lib/chat_server');//加载自定义模块
chatServer.listen(server);

chat_server.js

var socketio = require('socket.io');
var io;
var guestNumber = 1;
var nickNames = {
    
    };
var namesUsed = [];
var currentRoom = {
    
    };
var roomNames = new Set();

exports.listen = function(server) {
    
    
    io = socketio.listen(server);
    // 设置日志输出级别 0-error 1-warn 2-info 3-debug, 默认为3
    io.set('log level', 2);
    io.sockets.on('connection', function(socket) {
    
    
        guestNumber = assignGuestName(socket, guestNumber);

        roomNames.add('Lobby');
        joinRoom(socket, 'Lobby');  //用户连接上时把他放入聊天室Lobby

        //处理用户的消息, 更名以及聊天室的创建与变更
        handleMessageBroadcasting(socket);
        handleNameChangeAttempts(socket);
        handleRoomJoining(socket);

        //用户发出请求时, 展示所有聊天室列表
        socket.on('roomlist', function () {
    
    
            socket.emit('roomlist', {
    
    text: Array.from(roomNames)});
        });

        //定义用户断开连接后的清除逻辑
        handleClientDisconnection(socket);

    });
}

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

function joinRoom(socket, 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.sockets.clients(room);
    if (usersInRoom.length > 1) {
    
    
        var usersInRoomSummary = 'Users currently in ' + room + ': ';
        for (var index in usersInRoom) {
    
    
            var usersSocketId = usersInRoom[index].id;
            if (usersSocketId != socket.id) {
    
    
                if (index > 0) {
    
    
                    usersInRoomSummary += ', ';
                }
                usersInRoomSummary += nickNames[usersSocketId];
            }
        }
        usersInRoomSummary += '.';
        socket.emit('message', {
    
    text: usersInRoomSummary});
    }
}

function handleNameChangeAttempts(socket) {
    
    
    socket.on('nameAttempt', function(name) {
    
    
        if (name.indexOf('Guest') == 0) {
    
    
            socket.emit('nameResult', {
    
    
                success: false,
                message: 'Names cannot 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]);
        roomNames.add(room.newRoom);
        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];
    });
}

源码地址

https://gitee.com/3281328128/chat-room.git

下载之后,执行以下命令启动

npm install
node server.js

猜你喜欢

转载自blog.csdn.net/modelmd/article/details/127857411