nodejs+express+socket.io实现多人聊天室
(记录学习中遇到的问题,以及实现的思路,做个备忘吧)
一、安装配置
1.nodejs(传送门)点这里
2、安装express,我是安装的3版本,按住shift键然后鼠标右击,出现下图

然后在出现的cmd命令行中输入 npm install express@3 --save-dev (@3是版本,--save是项目安装,安装好了会在项目中的node_modules中找到)

由于4.x版本中将命令工具单独分出来了(https://github.com/expressjs/generator),所有要先按装express-generator,否则创建项目时,会提示express命令没找到,具体解决办法请百度
3、安装socket.io
在自己的项目目录运行(同上)输入 npm install socket.io --save
因为客户端也需要引入socket.io所以我在node_modules中找到了socket.io-client文件夹下的socket.io.js,并且复制到了js文件夹中,以便于引用。

以下为详细项目目录

基本就是这样了,现在开始写代码
二、代码编写
1.我的思路
这里先记录下我理解的思路,首先浏览器客户端发送A事件,而在服务器端监听A事件,如果服务器监听到A事件,进行逻辑处理,处理完毕后,广播B事件,这里的B事件,会广播到每一个与服务器建立socket链接的客户端。
然后在客户端中监听B事件,然后再做渲染处理。
2.引入文件
在index页面引入jq和socket.io.js,以及自己创建的js文件
<script src='dep/bootstrap-3.3.5/js/jquery-1.11.3.js'></script>
<script src='./js/socket.io.js'></script>
<script src=js/socketTest.js></script>
3.代码编写
1).socketTest.js
var socket = io();/*引入socket*/ $(document).keypress(function (event) { if(event.keyCode == 13){ $('#sendMes').trigger('click') } }); $('#mesFrom').submit(function () { var someMsg = $('#MessageValue').val(); nickName || (nickName='匿名'+''+parseInt(Math.random()*10000+1)+'');/*判断用户是否输入用户名,没有则为匿名+1000的随机数*/ $('.userNickName').html(nickName) if ($.trim(someMsg) !== '') {/*判断提交的信息是否为空*/ socket.emit('chatmessage', {nickName: nickName, Msg: someMsg});/*发布chatmessage事件,并且传递一个对象*/ $('#MessageValue').val(''); } return false; }); socket.on('message', function (obj) {/*监听服务器发送的message事件*/ $('#someMessage').append($('<li>').text(obj.name + ':' + '(' + obj.sendMsgTime + ')')); $('#someMessage').append($('<span class="msgStyle">'+obj.chatMsg+'</span>')); var outinUlHeight=$('#someMessage').height(); var outsideWrapHeight=$('.messageBox').height(); $('.messageBox').scrollTop(outinUlHeight-outsideWrapHeight+10);/*让最新的消息显示在底部*/ });
2).服务器文件,app.js
const express = require("express");/*引入express*/
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.configure(function () {
app.use(express.logger("dev"));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + "/src/public"));/*设置静态目录,当请求为/的时候,默认为public/index.html文件*/
app.use(express.errorHandler());
})
var person = {};
var user=[];
var allUserNum=0;
io.on('connection', function (socket) {
allUserNum++;/*客户端每次建立连接 在线人数+1*/
socket.on('chatmessage', function (msg) {/*监听客户端发送的chatmessage事件*/
person.name = msg.nickName;
person.chatMsg = msg.Msg;
person.AllPerson = allUserNum;
var sendMsgTime = getDate();
person.sendMsgTime = sendMsgTime;
io.emit('message', person);/*向与服务器建立socket连接的客户端广播message事件*/
});
});
http.listen(8888, function () {
console.log('listening on *:8888');
});
function getDate() {
var Mydate = new Date();
return Mydate.toLocaleString()
}
以下为详细代码;
index.html
<!doctype html>
<html>
<head>
<meta name="viewport" content="initial-scale=1, user-scalable=0, minimal-ui">
<title>Socket.IO chat</title>
<link rel="stylesheet" href="dep/bootstrap-3.3.5/css/bootstrap.css">
<link rel="stylesheet" href="dep/iconfont/iconfont.css">
<link rel="stylesheet" href="css/index.css">
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<!--[if IE 7]>
<script src="js/json2.js"></script>
<![endif]-->
</head>
<body>
<nav class="navbar navbar-default nav-bar" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse"
data-target="#example-navbar-collapse">
<span class="sr-only">切换导航</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#"><i class='iconfont logo-icon'></i><span class='icon-title'>WeiChat</span></a>
</div>
<div class="collapse navbar-collapse" id="example-navbar-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">公共聊天室</a></li>
<li><a href="#">一对多(客服模式)</a></li>
<li><a href="#">一对一(私信模式)</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
更多<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="#">暂无更多</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section class='row' id='chatBox'>
<div class='chat-content col-lg-offset-4 col-lg-4 col-md-4 col-md-offset-4 col-sm-12' style='padding-left: 0;padding-right: 0'>
<h4 class='content-title'>
<span class='content-left-title'>
<i class='iconfont chatroom-title-icon'></i><span id='room-title'>公共聊天室</span>
</span>
<span class='content-right-title'>
<div id="userInfo-wrap"><span class="userNickName"></span><i class='glyphicon glyphicon-user padding10'></i></div>
<div id="userNum-wrap"><span class="allUserInline">当前在线:<span id="allInline"></span></span><i class='glyphicon glyphicon-ok-sign inline-color padding101'></i></div>
</span>
</h4>
<div class='messageBox'>
<ul id='someMessage'>
<!--这是聊天记录显示区域-->
</ul>
</div>
<div class='sendmessageBox'>
<div class='chatFun'>
<span><i class='iconfont someImg'></i></span>
</div>
<form action="##" id='mesFrom'>
<textarea name="" id='MessageValue' style='white-space: pre;resize: none;' ></textarea>
<div class=btn-positoin><button id='sendMes'>发送 <span class='glyphicon glyphicon-triangle-bottom'></span> </button></div>
</form>
</div>
</div>
</section>
<!--模态框-->
<div class="modal fade filter" tabindex="-1" role="dialog" aria-labelledby="gridSystemModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="gridSystemModalLabel"> 取个昵称吧</h4>
</div>
<div class="modal-body">
<div class="row">
<div class='nickName-wrap'>
<div class=input-wrap>
<input type="text" id='nickNameInput'><button class=' btn-sm random-btn'>随机</button>
<span id='usernameInfo'></span>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<!--<button type="button" class="btn btn-default" data-dismiss="modal">不取</button>-->
<button type="button" class="enter-inputName btn">就这个</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<button style='display: none' type="button" id='nickNameModal' class=" btn-lg" data-toggle="modal" data-target=".modal"></button>
</body>
<script src='dep/bootstrap-3.3.5/js/jquery-1.11.3.js'></script>
<script src='dep/bootstrap-3.3.5/js/bootstrap.min.js'></script>
<script src=js/socketTest.js></script>
<script src='./js/socket.io.js'></script>
</html>
index.css
*{ margin: 0; padding: 0; font-family: 'Microsoft Ya Hei'; } html{ font-size: 62.5%; } /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸*/ /*::-webkit-scrollbar*/ /*{*/ /*width: 5px;*/ /*height: 5px;*/ /*background-color: #F5F5F5;*/ /*}*/ /*!*定义滚动条轨道 内阴影+圆角*!*/ /*::-webkit-scrollbar-track*/ /*{*/ /*-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);*/ /*border-radius: 10px;*/ /*background-color: #F5F5F5;*/ /*}*/ /*!*定义滑块 内阴影+圆角*!*/ /*::-webkit-scrollbar-thumb*/ /*{*/ /*border-radius: 10px;*/ /*-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);*/ /*background-color: #45cd94;*/ /*}*/ #chatBox{ margin: 0 auto; /*height: 500px;*/ background-color: white; /*outline: 1px solid red;*/ } .chat-content{ border: 1px solid rgba(157, 157, 157, 0.56); border-radius: 5px; padding-bottom: 5px; height: 460px; } .title{ text-align: center; color: #fff; font-size: 4rem; background-color: rgba(0, 0, 0, 0.51); } .content-title{ height: 60px; line-height: 60px; margin: 0; padding-left: 3% ; border-top:5px solid #3fc18e; border-top-left-radius: 5px; border-top-right-radius: 5px; background-color: #eee; } .messageBox{ height: 250px; overflow-y: scroll; /*outline: 1px solid black;*/ } .msgStyle{ position: relative; left: 15px; top:0; padding: 6px 9px; max-width: 45%; line-height: 1.4rem; display: inline-block; background-color: #eee; border-radius: 2px; } .msgStyle:after{ content: ''; } .sendmessageBox{ height: 100px; border-top: 1px solid #eee; } .chatFun{ margin: 0 1% 0 1%; height: 35%; width: 98%; padding-top: 1%; cursor: pointer; /*vertical-align: middle;*/ /*outline: 1px solid black;*/ } .someImg{ font-size: 1.9rem; } #mesFrom{ height: 150px; /*outline: 1px solid gold;*/ } #MessageValue{ text-align:left; border-bottom-left-radius:4px; border-bottom-right-radius:4px; border:1px solid #c8cccf; color:#6a6f77; -web-kit-appearance:none; -moz-appearance: none; display:block; outline:0; text-decoration:none; width:98%; margin-left: 1%; height: 60px; display: inline-block; padding-left: 10px; font-size: 15px; } #sendMes{ margin-right: 1%; margin-top: 1%; width: 25%; height: 30px; /*padding: 5px 9px 5px 9px;*/ color: #fff; background-color: #3eb381; border: none; border-radius: 4px; display: inline-block; } .btn-positoin{ text-align: right; } #sendMes:hover{ cursor: pointer; background-color: #34936a; } .logo-icon{ font-size: 3rem; color: #34936a; } .chatroom-title-icon{ color: #999; font-size: 1.3rem; padding-right: 3%; } .content-left-title{ float: left; width: 30%; height: 55px; } .content-right-title{ float: right; text-align: right; padding-right: 2%; width:65%; height: 55px; line-height: 55px; font-size: 1.3rem; color: #999; } #userInfo-wrap{ width: 45%; height: 55px; float: left; } .userNickName{ text-overflow: ellipsis; display: inline-block; white-space:nowrap; overflow: hidden; float: right; } .allUserInline{ display: inline-block; float: right; } #userNum-wrap{ float: right; width: 53%; } .icon-title{ color: #327951; } .padding10{ padding-left: 10px; padding-right: 5px; line-height: 55px; float: right; } .padding101{ margin-right: 5px; line-height: 55px; float: right; } .inline-color{ color: #3eb381; } #someMessage>li{ padding: 1% 2% 1% 1%; } .nav-bar{ margin-bottom: 0; } #room-title{ font-size: 1.5rem; } .nickName-wrap{ text-align: center; padding: 2% 0 2% 0; } #nickNameInput{ width: 48%; height: 30px; max-height: 35px; min-height: 25px; border:1px solid #e2e2e2; padding-left: 2%; } .input-wrap{ width: 100%; display: inline-block; text-align: center; } .random-btn{ margin-left: 1%; margin-top: -3px; background-color: #3eb381; border:1px solid #3eb381; color:white; } .enter-inputName{ width: 100%; background-color: #3eb381; border:1px solid #3eb381; color:white; } .modal-title{ color: #777; text-align: center; } #usernameInfo{ display: block; text-align: center; color: #a83940; font-size: 1rem; margin-top: 3%; }
app.js
const express = require("express");/*引入express*/
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.configure(function () {
app.use(express.logger("dev"));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(__dirname + "/src/public"));/*设置静态目录,当请求为/的时候,默认为public/index.html文件*/
app.use(express.errorHandler());
})
var person = {};
var user=[];
var allUserNum=0;
io.on('connection', function (socket) {
allUserNum++;/*客户端每次建立连接 在线人数+1*/
socket.on('chatmessage', function (msg) {/*监听客户端发送的chatmessage事件*/
person.name = msg.nickName;
person.chatMsg = msg.Msg;
person.AllPerson = allUserNum;
var sendMsgTime = getDate();
person.sendMsgTime = sendMsgTime;
io.emit('message', person);/*向与服务器建立socket连接的客户端广播message事件*/
});
socket.on('allUser',function (msg) {
io.emit('allUser',allUserNum)
})
});
app.get('/searchAllPerson.do',function (req,resp) {
resp.send(allUserNum)
})
app.get('/searchUserName.do',function (req,resp) {
resp.send(user)
})
app.post('/userResigte.do',function (req,resp) {
var name = req.body.username;
user.push(name);
resp.send('ok')
})
http.listen(8888, function () {
console.log('listening on *:8888');
});
function getDate() {
var Mydate = new Date();
return Mydate.toLocaleString()
}
socketTest.js
window.onload=function () { /*检测ie版本,暂时不支持ie7,未做ie7兼容处理*/ var browser=navigator.appName var b_version=navigator.appVersion var version=b_version.split(";"); var trim_Version=version[1].replace(/[ ]/g,""); if(browser=="Microsoft Internet Explorer" && trim_Version=="MSIE7.0") { alert("暂时不支持IE 7.0,请更新您的浏览器。"); } var nickName; /*用户注册----start-------*/ $('#nickNameModal').trigger('click');/*页面加载显示模态框*/ $('.random-btn').click(function () {/*随机选取名字*/ $(this).val(''); var adjWord = ['开心的','忧伤的','快乐的','愉快的','难过的','孤单的','无聊的','阳光的','帅气的','英俊的','看起来傻傻的']; var nWord = ['馒头','二哈','胡萝卜','猫咪','帅哥','美女','丝瓜','南瓜','冬瓜','哈密瓜','木瓜']; var firstName=adjWord[parseInt(Math.random()*10)]; var lastName=nWord[parseInt(Math.random()*10)]; $('#nickNameInput').val(firstName+lastName) }); $('.enter-inputName').click(function () {/*提交用户姓名*/ nickName =$('#nickNameInput').val(); if(nickName!==''){ userResig(nickName); }else {/*判断是否注册名字,没有就显示匿名+随机码*/ $('#usernameInfo').html('您的身份将会是’匿名‘'); nickName='匿名'+''+parseInt(Math.random()*10000+1)+''; userResig(nickName) } }); function userResig(nickName) { $.ajax({ url:'/userResigte.do', type:'post', data:'username='+nickName, success:function (result) { if(result==='ok'){ $('.filter').trigger('click') $('.userNickName').html(nickName) $('#MessageValue').focus(); } } }) } /*用户注册--------end---------*/ /*用户发送信息-----start--------*/ var socket = io();/*引入socket*/ $(document).keypress(function (event) { if(event.keyCode == 13){ $('#sendMes').trigger('click') } }); $('#mesFrom').submit(function () { var someMsg = $('#MessageValue').val(); nickName || (nickName='匿名'+''+parseInt(Math.random()*10000+1)+'');/*判断用户是否输入用户名,没有则为匿名+1000的随机数*/ $('.userNickName').html(nickName) if ($.trim(someMsg) !== '') {/*判断提交的信息是否为空*/ socket.emit('chatmessage', {nickName: nickName, Msg: someMsg});/*发布chatmessage事件,并且传递一个对象*/ $('#MessageValue').val(''); } return false; }); socket.on('message', function (obj) {/*监听服务器发送的message事件*/ $('#someMessage').append($('<li>').text(obj.name + ':' + '(' + obj.sendMsgTime + ')')); $('#someMessage').append($('<span class="msgStyle">'+obj.chatMsg+'</span>')); var outinUlHeight=$('#someMessage').height(); var outsideWrapHeight=$('.messageBox').height(); $('.messageBox').scrollTop(outinUlHeight-outsideWrapHeight+10);/*让最新的消息显示在底部*/ }); socket.emit('allUser', {nickName:'s'}); socket.on('allUser',function (data) { $('#allInline').html(data) }) /*用户发送信息-----end--------*/ };
GitHub地址:还没弄。
博客新人,如果有错,希望告知,谢谢。

浙公网安备 33010602011771号