HTML5——WebSocket:基于Node.js的网络聊天室
2021/4/18 20:25:30
本文主要是介绍HTML5——WebSocket:基于Node.js的网络聊天室,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
Day12
今日份内容:使用WebSocket制作基于Node.js的网络聊天室
WebSocket是一种基于TCP协议的通信技术,与传统HTTP有一定区别。
WebSocket
- 了解WebSocket通信机制
- 熟悉WebSocket API接口
- 使用WebSocket技术实现双向通信
- 了解Notification消息提醒机制
内容
- 配置Node.js环境
- 项目初始化
- 安装Express、WebSocket、node_uuid框架
- 服务端实现
- 客户端实现
代码
// index.js var express = require('express'); const http = require('http'); const url = require('url'); const WebSocket = require('ws'); const uuid = require('node-uuid'); var app = express(); //下面会修改临时文件的存储位置 app.use(express.static('public')); //设置http服务监听的端口号 app.set('port', process.env.PORT || 3000); app.listen(app.get('port'), function() { console.log("Express started on localhost:" + app.get('port') + ':press Ctrl-C to terminate.'); }); //浏览器访问localhost会输出一个html文件 app.get('/', function(req, res) { res.type('text/html'); res.sendFile('./index.html'); }); const server = http.createServer(app); const wss = new WebSocket.Server({ server }); server.listen(8080, function listening() { console.log('Listening on %d', server.address().port); }); var connections = []; var userList = []; var chatList = []; var headImages = ["head1", "head2", "head3", "head4", "head5"]; wss.on('connection', function connection(ws, req) { var currentUser; var client_uuid = uuid.v4(); connections.push({ "id": client_uuid, "ws": ws }); console.log('&&&&&client[%s]连接成功!&&&&&', client_uuid); //用户连接时,获得在线用户列表 ws.send(getUsersOnLine()); ws.on('message', function incoming(message) { let json = JSON.parse(message); //当用户发出登录请求时 if (json.op == "login") { let userName = json.userName; let loginTime = new Date(); let index = Math.ceil(Math.random() * (headImages.length)); //封装登录用户信息,以便保存到WebSocket中 currentUser = { 'userName': userName, 'loginTime': loginTime, 'headImages': headImages[index] }; userList.push({ "id": client_uuid, "user": currentUser }); console.log('########client[%s]登录成功########', currentUser); broadCast(getUsersOnLine()); broadCastNotification(getNewUser(currentUser.userName), ws); //发送用户登录会话 ws.send(getUserWithConnectionInfo(client_uuid)); } else if (json.op = "chat") { let connectionId = json.connectionId; let chatMessage = json.chatMessage; let time = json.time; let user = getUserFromUserList(connectionId); let msg = { 'user': user, 'charMessage': charMessage, 'time': time }; chatList.push({ "id": client_uuid, "msg": msg }); broadCast(getAllMessage()); } }); ws.on('close', function() { for (var i in connections) { if (connections[i].ws == ws) { connections.pop(ws); break; } } if (currentUser != null && currentUser.userName != null) { userList.pop(currentUser); broadCastNotification(getUserOffLine(currentUser.userName), ws); broadCast(getUsersOnLine()); } ws.close(); }); }); function onLineList(message, ws) { ws.send(message); } //向客户端以数组形式发送在线用户列表 function broadCast(message) { for (var i in connections) { try { if (connections[i].ws.readyState === WebSocket.OPEN) { //参数为字符串类型 connections[i].ws.send(Message); } } catch (e) { console.log(e); connections.pop(connections[i]); } } } //广播通知消息 function broadCastNotification(message, ws) { for (var i in connections) { try { if (connections[i].ws.readyState === WebSocket.OPEN && connections[i].ws != ws) { //参数为字符串类型 connections[i].ws.send(message); } } catch (e) { //TODO handle the exception console.log(e); connections.pop(connections[i]); } } } //返回现在用户列表,并以字符串形式返回 function getUsersOnLine() { let jsonObject = {}; jsonObject.users = userList; jsonObject.contentType = 'userOnLineList'; return JSON.stringify(jsonObject); } //获得新用户上线信息,并以字符串形式返回 function getNewUser(userName) { let jsonObject = {}; jsonObject.userName = userName; jsonObject.contentType = 'newUserOnLine'; return JSON.stringify(jsonObject); } //封装离散用户 function getUserOffLine(userName) { let jsonObject = {}; jsonObject.userName = userName; jsonObject.contentType = 'userOffLine'; return JSON.stringify(jsonObject); } //返回指定的客户信息 function getUserWithConnectionInfo(connectionId) { let jsonObject = {}; jsonObject.connectionId = connectionId; jsonObject.contentType = "userSession"; return JSON.stringify(jsonObject); } //根据connectionId查找在线用户列表 function getUserFromUserList(connectionId) { for (var i in userList) { if (userList[i].id == connectionId) { return userList[i].user; } } return null; } //返回所有的聊天信息 function getAllMessage() { let jsonObject = {}; jsonObject.messages = chatList; jsonObject.contentType = 'chatMessages'; return JSON.stringify(jsonObject); }
// clinetWebSocket.js var serverAddress = document.getElementById("serverAdress").value; var serverPort = document.getElementById("serverPort").value; var url = "ws://" + serverAddress + ":" + serverPort + "/ChatRoom_modify/chatRoomWebsocket"; var webSocket = new WebSocket(url); var userName; //用户注册 function loginUser() { userName = document.getElementById("userName").value; var user = new User("login", userName); //界面模块切换 document.getElementById("chatPart").style.display = "block"; document.getElementById("configure").style.display = "none"; document.getElementById("messages").style.display = "block"; document.getElementById("connectStatus").style.display = "none"; document.getElementById("serverAdressTxt").innerHTML = serverAddress; document.getElementById("serverPortTxt").innerHTML = serverPort; document.getElementById("userNameTxt").innerHTML = userName; //发送注册信息 webSocket.send(JSON.stringify(user)); } //发送聊天信息 function sendMessage() { var chatMessage = document.getElementById("chatMessage"); var connectionId = document.getElementById("connectionId").value; var message = new Message('chat', connectionId, chatMessage.value, getTime()); chatMessage.value = ''; webSocket.send(JSON.stringify(message)); } function User(op, userName) { this.op = op; this.userName = userName; } function Message(op, connectionId, chatMessage, time) { this.op = op; this.connectionId = connectionId; this.chatMessage = chatMessage; this.time = time; } function getTime() { var now = new Date(); return now.getFullYear() + "/" + (now.getMonth() + 1) + "/" + now.getDate() + "" + now.getHours() + ":" + now.getMinutes() + ":" + now.getSeconds(); } webSocket.onerror = function(event) { alert(event.data); }; //与WebSocket建立连接 webSocket.onopen = function(event) { document.getElementById('connectDiv').className = "online-img"; }; //处理服务器返回的信息 webSocket.onmessage = function(event) { var userList = ""; var messageList = ""; var returnContent = eval("(" + event.data + ")"); console.log(returnContent); if (returnContent.contentType == "userSession") { document.getElementById('connectionId').value = returnContent.connectionId; } if (returnContent.contentType == "userOnLineList") { var users = returnContent.users; for (var i = 0; i < users.length; i++) { userList += '<li><span class="' + users[i].user.headImages + '"></span>' + user[i].user.userName + '</li>'; } document.getElementById('userOnLine').innerHTML = userList; document.getElementById('userList').className = "none-img none"; } if (returnContent.contentType == "newUserOnLine") { var userName = returnContent.userName; NotificationHandler.showNotification(userName, "上线"); } if (returnContent.contentType == "newUserOffLine") { var userName = returnContent.userName; NotificationHandler.showNotification(userName, "离线"); } if (returnContent.contentType == "chatMessages") { var messages = returnContent.messages; var userName = document.getElementById("userNameTxt").innerHTML; for (var i = messages.length - 1; i >= 0; i--) { if (messages[i].msg.user.userName == userName) { messageList += '<li><span class="chatcontent mychatcontent">' + messages[i].msg.chatMessage + '</span><span class="' + messages[i].msg.user.headImages + '"></span></li>'; } else { messageList += '<li><span class="' + messages[i].msg.user.headImages + '"></span><span class="chatcontent">' + messages[i].msg.chatMessage + '</span></li>'; } } document.getElementById('chatList').innerHTML = messageList; } };
<!-- index.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>基于Node.js实现网络聊天室</title> <link rel="stylesheet" type="text/css" href="css/main.css" /> </head> <body> <div class="container"> <!-- header --> <div class="header"> <div id="configure"> 服务器地址:<input type="text" id="serverAdress" value="localhost" /> 服务器端口:<input type="text" id="serverPort" value="8080" /> 昵称:<input type="text" id="userName" /> <input type="button" class="login-button" onclick="loginUser()" /> </div> <div id="chatPart" class="none"> 服务器地址:<span id="serverAdressTxt"></span> 服务器端口:<span id="serverPortTxt"></span> 昵称:<span id="userNameTxt"></span> </div> </div> <div class="banner"></div> <!-- content --> <div class="content"> <!-- left --> <div class="left"> <div id="connectStatus"> <h3 class="gray">用户状态</h3> <div id="connectDiv" class="offline-img"></div> </div> <div id="messages" class="none"> <h3 class="gray">聊天记录</h3> <input type="hidden" id="connectionId" /> <textarea rows="3" cols="30" id="chatMessage"></textarea> <input type="button" class="send-button" onclick="sendMessage()"> <ul id="chatList"> <li><span class="head1"></span> <span class="chatcontent">欢迎使用聊天室</span> </li> </ul> </div> </div> <!-- right --> <div class="right"> <h3 class="box">在线用户</h3> <div id="userOnLine" class="none-img"></div> <ul id="userOnLine"></ul> </div> </div> </div> <script type="text/javascript" src="js/notification.js"></script> <script type="text/javascript" src="js/clientWebSocket.js"></script> </body> </html>
结果
步骤详解
- 控制台使用npm init命令对项目初始化
- 控制台分别使用 npm install express --save-dev 命令、npm install ws --save-dev 命令来安装Express框架、npm install node-uuid --save-dev 命令来安装Express、WebSocket、node_uuid框架
- 目录结构
- 创建服务端脚本index.js ,使用WebSocket框架完成创建服务端
- 创建客户端脚本clientWebSocket.js ,完成WebSocket客户端
- 实现网络聊天室主界面index.html
- 最后在控制台中使用 node index.js 命令启动Node.js服务器,在浏览器中输入 localhost:3000 网址进入测试。
PS
以后可能会用其他工具再次实现这个网络聊天室,到时候做的就会很好用很美观啦~
这篇关于HTML5——WebSocket:基于Node.js的网络聊天室的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-05-30React Native常用组件-点击组件
- 2024-05-30uniapp+vue3+uv-ui手机端后台OA管理模板
- 2024-05-29Python网络爬虫的时候json=就是让你少写个json.dumps()
- 2024-05-27React Native常用组件-展示组件
- 2024-05-27React Native常用组件-列表组件
- 2024-05-09vue3开发前端表单缓存自定义指令,移动端h5必备插件
- 2024-05-09React Hooks在class组件中的使用方式
- 2024-03-30[OIDC in Action] 2. 基于OIDC(OpenID Connect)的SSO(纯JS客户端)
- 2024-03-29terraform jsonencode
- 2024-03-13vuex-persist