Welcome 微信登录

首页 / 脚本样式 / JavaScript / 基于socket.io+express实现多房间聊天

socket.io简介

Socket.IO是一个开源的WebSocket库,它通过Node.js实现WebSocket服务端,同时也提供客户端JS库。Socket.IO支持以事件为基础的实时双向通讯,它可以工作在任何平台、浏览器或移动设备。

Socket.IO支持4种协议:WebSocket、htmlfile、xhr-polling、jsonp-polling,它会自动根据浏览器选择适合的通讯方式,从而让开发者可以聚焦到功能的实现而不是平台的兼容性,同时Socket.IO具有不错的稳定性和性能。
多房间聊天

socket.io提供rooms和namespace的API

用rooms的API就可以实现多房间聊天了,总结出来无外乎就是:join/leave room 和 say to room
// join和leaveio.on("connection", function(socket){ socket.join("some room"); // socket.leave("some room");});// say to roomio.to("some room").emit("some event"):io.in("some room").emit("some event"):
代码 github
新建文件夹chatapp-demo
chatapp-demo/package.json
{ "name": "chatapp-demo", "version": "1.0.0", "description": "multi room chat app demo, powered by socket.io", "main": "app.js", "dependencies": {"express": "^4.13.3","hbs": "^3.1.0","path": "^0.11.14","socket.io": "^1.3.6" }, "devDependencies": {}, "author": "wuyanxin", "license": "ISC"}
执行 npm install
服务端代码
增加文件 chatapp-demo/app.js
var express = require("express");var path = require("path");var IO = require("socket.io");var router = express.Router();var app = express();var server = require("http").Server(app);app.use(express.static(path.join(__dirname, "public")));app.set("views", path.join(__dirname, "views"));app.set("view engine", "hbs");// 创建socket服务var socketIO = IO(server);// 房间用户名单var roomInfo = {};socketIO.on("connection", function (socket) { // 获取请求建立socket连接的url // 如: http://localhost:3000/room/room_1, roomID为room_1 var url = socket.request.headers.referer; var splited = url.split("/"); var roomID = splited[splited.length - 1];// 获取房间ID var user = ""; socket.on("join", function (userName) {user = userName;// 将用户昵称加入房间名单中if (!roomInfo[roomID]) { roomInfo[roomID] = [];}roomInfo[roomID].push(user);socket.join(roomID);// 加入房间// 通知房间内人员socketIO.to(roomID).emit("sys", user + "加入了房间", roomInfo[roomID]); console.log(user + "加入了" + roomID); }); socket.on("leave", function () {socket.emit("disconnect"); }); socket.on("disconnect", function () {// 从房间名单中移除var index = roomInfo[roomID].indexOf(user);if (index !== -1) { roomInfo[roomID].splice(index, 1);}socket.leave(roomID);// 退出房间socketIO.to(roomID).emit("sys", user + "退出了房间", roomInfo[roomID]);console.log(user + "退出了" + roomID); }); // 接收用户消息,发送相应的房间 socket.on("message", function (msg) {// 验证如果用户不在房间内则不给发送if (roomInfo[roomID].indexOf(user) === -1) {return false;}socketIO.to(roomID).emit("msg", user, msg); });});// room pagerouter.get("/room/:roomID", function (req, res) { var roomID = req.params.roomID; // 渲染页面数据(见views/room.hbs) res.render("room", {roomID: roomID,users: roomInfo[roomID] });});app.use("/", router);server.listen(3000, function () { console.log("server listening on port 3000");});
客户端代码
新增chatapp/views/room.hbs
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>{{roomID}}</title> <style>#msglog, #messageInput { border: 1px solid #ccc; width: 500px; height: 350px; overflow-y: auto; font-size: 14px;}#messageInput { height: 80px;}.message { line-height: 22px;}.message .user { padding-right: 5px; padding-left: 5px; color: brown;}.sysMsg { color: #c1bfbf; padding-right: 5px; padding-left: 5px; font-size: 12px;}#users { width: 490px; padding: 0 5px 5px;} </style></head><body> 昵称: <span id="userName"></span> <br/> 房间: {{roomID}} <br/> 当前在线人数: <span id="count">{{users.length}}</span> <br/> 在线用户: <div id="users">{{users}}</div> <div id="msglog"> </div> <textarea name="message" id="messageInput"></textarea> <br/> 按Enter键发送 <button id="joinOrLeave">退出房间</button> <script src="/socket.io/socket.io.js"></script> <script src="/js/jquery.js"></script> <script>$(function () { // ----------设置昵称------------- var userName = ""; while ($("#userName").text().trim() === "") {userName = prompt("请设置你的昵称","");$("#userName").text(userName); } // ---------创建连接----------- var socket = io(); // 加入房间 socket.on("connect", function () {socket.emit("join", userName); }); // 监听消息 socket.on("msg", function (userName, msg) {var message = "" +"<div class="message">" +" <span class="user">" + userName + ": </span>" +" <span class="msg">" + msg + "</span>" +"</div>";$("#msglog").append(message);// 滚动条保持最下方$("#msglog").scrollTop($("#msglog")[0].scrollHeight);}); // 监听系统消息 socket.on("sys", function (sysMsg, users) {var message = "<div class="sysMsg">" + sysMsg + "</div>";$("#msglog").append(message);$("#count").text(users.length);$("#users").text(users); }); // 发送消息 $("#messageInput").keydown(function (e) {if (e.which === 13) { e.preventDefault(); var msg = $(this).val(); $(this).val(""); socket.send(msg);} }); // 退出房间 $("#joinOrLeave").click(function () {if ($(this).text() === "退出房间") { $(this).text("进入房间"); socket.emit("leave"); var msg = "你已经退出了房间,重新发言请点击"进入房间""; $("#msglog").append("<div class="sysMsg">"+msg+"</div>");} else { $(this).text("退出房间"); socket.emit("join", userName);} });}); </script></body></html>
新增 chatapp/public/index.html
<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title>demo</title></head><body> 欢迎您,骚年 <div><p>房间列表</p><ul> <li id="room_1"><a href="/room/room_1" target="_blank">1号房间</a></li> <li id="room_2"><a href="/room/room_2" target="_blank">2号房间</a></li> <li id="room_3"><a href="/room/room_3" target="_blank">3号房间</a></li> <li id="room_4"><a href="/room/room_4" target="_blank">4号房间</a></li> <li id="room_5"><a href="/room/room_5" target="_blank">5号房间</a></li> <li id="room_6"><a href="/room/room_6" target="_blank">6号房间</a></li> <li id="room_7"><a href="/room/room_7" target="_blank">7号房间</a></li> <li id="room_8"><a href="/room/room_8" target="_blank">8号房间</a></li> <li id="room_9"><a href="/room/room_9" target="_blank">9号房间</a></li> <li id="room_10"><a href="/room/room_10" target="_blank">10号房间</a></li></ul> </div></body></html>
运行效果

代码已放在github https://github.com/wuyanxin/chatapp-demo.git