聊天室
效果展示
websocket
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
HTML5 定义的 WebSocket 协议,能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。
前端实现
html语句只能实现非常简单的页面,重点在于css的渲染
登陆页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css" integrity="sha256-mmgLkCYLUQbXn0B1SRqzHar6dCnv9oZFPEC1g1cwlkk=" crossorigin="anonymous" /> <link rel="stylesheet" href="css/style.css" /> <title>聊天室</title> </head> <body> <div class="join-container"> <header class="join-header"> <h1><i class="fa fa-comments"></i> 聊天室</h1> </header> <main class="join-main"> <form action="chat.html"> <div class="form-control"> <label for="username">账户</label> <input type="text" name="username" id="username" placeholder="输入用户名" required /> </div> <div class="form-control"> <label for="room">房间</label> <select name="room" id="room"> <option value="philca的房间">philca的房间</option> </select> </div> <button type="submit" class="btn">加入聊天室</button> </form> </main> </div> </body> </html>
|
聊天页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.1/css/all.min.css" integrity="sha256-mmgLkCYLUQbXn0B1SRqzHar6dCnv9oZFPEC1g1cwlkk=" crossorigin="anonymous" /> <link rel="stylesheet" href="css/style.css" /> <title>聊天室</title> </head> <body> <div class="chat-container"> <header class="chat-header"> <h1><i class="fa fa-globe"></i> 聊天室</h1> <a id="leave-btn" class="btn">离开房间</a> </header> <main class="chat-main"> <div class="chat-sidebar"> <h3><i class="fas fa-comments"></i> 房间名</h3> <h2 id="room-name"></h2> <h3><i class="fas fa-users"></i> 用户</h3> <ul id="users"></ul> </div> <div class="chat-messages"></div> </main> <div class="chat-form-container"> <form id="chat-form"> <input id="msg" type="text" placeholder="输入信息" required autocomplete="off" /> <button class="btn"><i class="fas fa-paper-plane"></i> 发送</button> </form> </div> </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qs/6.9.2/qs.min.js" integrity="sha256-TDxXjkAUay70ae/QJBEpGKkpVslXaHHayklIVglFRT4=" crossorigin="anonymous" ></script> <script src="/socket.io/socket.io.js"></script> <script src="js/main.js"></script> </body> </html>
|
后端实现
将后端分为几个模块
消息传输
1 2 3 4 5 6 7 8 9 10 11
| const moment = require('moment');
function formatMessage(username, text) { return { username, text, time: moment().format('h:mm:ss a') }; }
module.exports = formatMessage;
|
以此来显示用户身份、消息内容、消息发送时间
用户行为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| const users = [];
function userJoin(id, username, room) { const user = { id, username, room };
users.push(user);
return user; }
function getCurrentUser(id) { return users.find(user => user.id === id); }
function userLeave(id) { const index = users.findIndex(user => user.id === id);
if (index !== -1) { return users.splice(index, 1)[0]; } } function getRoomUsers(room) { return users.filter(user => user.room === room); }
module.exports = { userJoin, getCurrentUser, userLeave, getRoomUsers };
|
用于判断用户加入的房间,加入房间、离开房间的行为
整体运行
需要引入socket.io模块,作用是实现服务器端与客户端的长连接
1
| const socketio = require('socket.io');
|
规定在3000端口显示
1 2 3
| const PORT = process.env.PORT || 3000;
server.listen(PORT, () => console.log(`Server running on port ${PORT}`));
|