socket.io简介

在Html5中存在着这样的一个新特性,引入了websocket,关于websocket的内部实现原理可以看这篇文章,这篇文章讲述了websocket无到有,根据协议,分析数据帧的头,进行构建websocket。虽然代码短,但可以很好地体现websocket的原理。
,这个特性提供了浏览器端和服务器端的基于TCP连接的双向通道。但是并不是所有的浏览器都支持websocket特性,故为了磨平浏览器间的差异,为开发者提供统一的接口,引入了socket.io模块。在不支持websoket的浏览器中,socket.io可以降级为其他的通信方式,比如有AJAX long polling ,JSONP Polling等。
模块安装
新建一个package.json文件,在文件中写入如下内容:
{
"name": "socketiochatroom",
"version": "0.0.1",
"dependencies": {
"socket.io": "*",
"express":"*"
}
}
npm install
执行完这句,node将会从npm处下载socket.io和express模块。
-
服务器端的实现
在文件夹中添加index.js文件,并在文件中写入如下内容:
/**
* Created by bamboo on 2016/3/31.
*/
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function (req, res) {
"use strict";
res.end("<h1>socket server</h1>")
});
/*在线人员*/
var onLineUsers = {};
/* 在线人数*/
var onLineCounts = 0;
/*io监听到存在链接,此时回调一个socket进行socket监听*/
io.on('connection', function (socket) {
console.log('a user connected');
/*监听新用户加入*/
socket.on('login', function (user) {
"use strict";
//暂存socket.name 为user.userId;在用户退出时候将会用到
socket.name = user.userId;
/*不存在则加入 */
if (!onLineUsers.hasOwnProperty(user.userId)) {
//不存在则加入
onLineUsers[user.userId] = user.userName;
onLineCounts++;
}
/*一个用户新加入,向所有客户端监听login的socket的实例发送响应,响应内容为一个对象*/
io.emit('login', {onLineUsers: onLineUsers, onLineCounts: onLineCounts, user: user});
console.log(user.userName, "加入了聊天室");//在服务器控制台中打印么么么用户加入到了聊天室
});
/*监听用户退出聊天室*/
socket.on('disconnect', function () {
"use strict";
if (onLineUsers.hasOwnProperty(socket.name)) {
var user = {userId: socket.name, userName: onLineUsers[socket.name]};
delete onLineUsers[socket.name];
onLineCounts--;
/*向所有客户端广播该用户退出群聊*/
io.emit('logout', {onLineUsers: onLineUsers, onLineCounts: onLineCounts, user: user});
console.log(user.userName, "退出群聊");
}
})
/*监听到用户发送了消息,就使用io广播信息,信息被所有客户端接收并显示。注意,如果客户端自己发送的也会接收到这个消息,故在客户端应当存在这的判断,是否收到的消息是自己发送的,故在emit时,应该将用户的id和信息封装成一个对象进行广播*/
socket.on('message', function (obj) {
"use strict";
/*监听到有用户发消息,将该消息广播给所有客户端*/
io.emit('message', obj);
console.log(obj.userName, "说了:", obj.content);
});
});
/*监听3000*/
http.listen(3000, function () {
"use strict";
console.log('listening 3000');
});
运行服务器端程序
node index.js
输出
listening 3000
此时在浏览器中打开localhost:3000会得到这样的结果:
原因是在代码中只对路由进行了如下设置
app.get('/', function (req, res) {
"use strict";
res.end("<h1>socket server</h1>")
});
服务器端主要是提供socketio服务,并没有设置路由。
客户端的实现
在客户端建立如下的目录和文件,其中json3.min.js可以从网上下载到。
client
- - - client.js
- - - index.html
- - - json3.min.js
- - - style.css
在index.html中
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="format-detection" content="telephone=no"/>
<meta name="format-detection" content="email=no"/>
<title>1301群聊</title>
<link rel="stylesheet" type="text/css" href="./style.css"/>
<script src="http://realtime.plhwin.com:3000/socket.io/socket.io.js"></script>
<script src="./json3.min.js"></script>
</head>
<body>
<div id="loginbox">
<div style="width: 260px;margin: 200px auto;">
输入你在群聊中的昵称
<br/>
<br/>
<input type="text" style="width:180px;" placeholder="请输入用户名" id="userName" name="userName"/>
<input type="button" style="width: 50px;" value="提交" onclick="CHAT.userNameSubmit();"/>
</div>
</div>
<div id="chatbox" style="display: none;">
<div style="background: #3d3d3d;height: 28px;width: 100%;font-size: 12px">
<div style="line-height: 28px;color:#fff;">
<span style="text-align: left;margin-left: 10px;">1301群聊</span>
<span style="float: right;margin-right: 10px"><span id="showUserName"></span>|
<a href="javascript:;" onclick="CHAT.logout()" style="color: #fff;">退出</a></span>
</div>
</div>
<div id="doc">
<div id="chat">
<div id="message" class="message">
<div id="onLineCounts"
style="background: #EFEFF4; font-size: 12px;margin-top: 10px;margin-left: 10px;color: #666;">
</div>
</div>
<div class="input-box">
<div class="input">
<input type="text" maxlength="140" placeholder="输入聊天内容 " id="content" name="content" >
</div>
<div class="action">
<button type="button" id="mjr_send" onclick="CHAT.submit();">提交</button>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="./client.js"></script>
</body>
</html>
在client.js中
/**
* Created by bamboo on 2016/3/31.
*/
/*即时运行函数*/
(function () {
"use strict";
var d = document,
w = window,
dd = d.documentElement,
db = d.body,
dc = d.compatMode === "CSS1Compat",
dx = dc ? dd : db,
ec = encodeURIComponent,
p = parseInt;
w.CHAT = {
msgObj: d.getElementById("message"),
screenHeight: w.innerHeight ? w.innerHeight : dx.innerHeight,
userName: null,
userId: null,
socket: null,
/*滚动条始终在最底部*/
scrollToBottom: function () {
w.scrollTo(0, this.msgObj.clientHeight);
},
/*此处仅为简单的刷新页面,当然可以做复杂点*/
logout: function () {
// this.socket.disconnect();
w.top.location.reload();
},
submit: function () {
var content = d.getElementById('content').value;
if (content != '') {
var obj = {
userId: this.userId,
userName: this.userName,
content: content
};
//如在服务器端代码所说,此对象就行想要发送的信息和发送人组合成为对象一起发送。
this.socket.emit('message', obj);
d.getElementById('content').value = '';
}
return false;
},
/**客户端根据时间和随机数生成ID,聊天用户名称可以重复*/
genUid: function () {
return new Date().getTime() + "" + Math.floor(Math.random() * 889 + 100);
},
/*更新系统信息
主要是在客户端显示当前在线人数,在线人列表等,当有新用户加入或者旧用户退出群聊的时候做出页面提示。*/
updateSysMsg: function (o, action) {
var onLineUsers = o.onLineUsers;
var onLineCounts = o.onLineCounts;
var user = o.user;
//更新在线人数
var userHtml = '';
var separator = '';
for (var key in onLineUsers) {
if (onLineUsers.hasOwnProperty(key)) {
userHtml += separator + onLineUsers[key];
separator = '、';
}
}
//插入在线人数和在线列表
d.getElementById('onLineCounts').innerHTML = '当前共有' + onLineCounts + "在线列表: " + userHtml;
//添加系统消息
var html = '';
html += '<div class="msg_system">';
html += user.userName;
html += (action === "login") ? "加入了群聊" : "退出了群聊";
html += '</div>';
var section = d.createElement('section');
section.className = 'system J-mjrlinkWrap J-cutMsg';
section.innerHTML = html;
this.msgObj.appendChild(section);
this.scrollToBottom();
},
/*用户提交用户名后,将loginbox设置为不显示,将chatbox设置为显示*/
userNameSubmit: function () {
var userName = d.getElementById('userName').value;
if (userName != '') {
d.getElementById('userName').value = '';
d.getElementById('loginbox').style.display = 'none';
d.getElementById('chatbox').style.display = 'block';
this.init(userName);//调用init方法
}
return false;
},
//用户初始化
init: function (userName) {
//随机数生成uid
this.userId = this.genUid();
this.userName = userName;
d.getElementById('showUserName').innerHTML = this.userName;//[newpidian]|[退出]
this.scrollToBottom();
//连接socketIO服务器,newpidian的IP地址
this.socket = io.connect('192.168.3.155:3000');
//向服务器发送某用户已经登录了
this.socket.emit('login', {userId: this.userId, userName: this.userName});
//监听来自服务器的login,即在客户端socket.emit('login ')发送后,客户端就会收到来自服务器的
// io.emit('login', {onLineUsers: onLineUsers, onLineCounts: onLineCounts, user: user});
/*监听到有用户login了,更新信息*/
this.socket.on('login', function (o) {
//更新系统信息
CHAT.updateSysMsg(o, 'login');
});
/*监听到有用户logout了,更新信息*/
this.socket.on('logout', function (o) {
CHAT.updateSysMsg(o, 'logout');
});
//var obj = {
// userId: this.userId,
// userName: this.userName,
// content: content
//};
/*监听到有用户发送消息了*/
this.socket.on("message", function (obj) {
//判断消息是不是自己发送的
var isMe = (obj.userId === CHAT.userId);
var contentDiv = '<div>' + obj.content + '</div>';
var userNameDiv = '<span>' + obj.userName + '</span>';
var section = d.createElement('section');
if (isMe) {
section.className = 'user';
section.innerHTML = contentDiv + userNameDiv;
} else {
section.className = 'service';
section.innerHTML = userNameDiv + contentDiv;
}
CHAT.msgObj.appendChild(section);
CHAT.scrollToBottom();
});
}
}
/*控制键键码值(keyCode)
按键 键码 按键 键码 按键 键码 按键 键码
BackSpace 8 Esc 27 Right Arrow 39 -_ 189
Tab 9 Spacebar 32 Dw Arrow 40 .> 190
Clear 12 Page Up 33 Insert 45 /? 191
Enter 13 Page Down 34 Delete 46 `~ 192
Shift 16 End 35 Num Lock 144 [{ 219
Control 17 Home 36 ;: 186 \| 220
Alt 18 Left Arrow 37 =+ 187 ]} 221
Cape Lock 20 Up Arrow 38 ,< 188 '" 222
* */
//通过“回车键”提交用户名
d.getElementById('userName').onkeydown = function (e) {
console.log(e);
e = e || event;
if (e.keyCode === 13) {
CHAT.userNameSubmit();
}
};
//通过“回车键”提交聊天内容
d.getElementById('content').onkeydown = function (e) {
e = e || event;
if (e.keyCode === 13) {
CHAT.submit();
}
};
})();
style.css
秘密
运行结果
服务器端已经运行,现将客户端也运行起来得到下图:
添加了new和pidian两个用户,并发送信息和进行退出,得到下面的结果:
以上所述是小编给大家介绍的基于Nodejs利用socket.io实现多人聊天室,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
# nodejs
# socket
# 聊天室
# socket.io
# socket.io聊天室
# NodeJS实现一个聊天室功能
# nodejs+express搭建多人聊天室步骤
# Nodejs实现多房间简易聊天室功能
# Node.js websocket使用socket.io库实现实时聊天室
# Node.js利用Net模块实现多人命令行聊天室的方法
# Node.js中使用socket创建私聊和公聊聊天室
# AngularJS+Node.js实现在线聊天室
# 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
# nodejs实现的一个简单聊天室功能分享
# node+socket实现简易聊天室功能
# 客户端
# 是在
# 随机数
# 将会
# 回车键
# 不存在
# 这篇文章
# 设置为
# 小编
# 器中
# 就会
# 很好
# 也会
# 出了
# 在这
# 在此
# 说了
# 如有
# 你在
相关文章:
如何配置IIS站点权限与局域网访问?
建站OpenVZ教程与优化策略:配置指南与性能提升
北京制作网站的公司排名,北京三快科技有限公司是做什么?北京三快科技?
如何在IIS中新建站点并配置端口与物理路径?
如何制作算命网站,怎么注册算命网站?
如何选择香港主机高效搭建外贸独立站?
PHP正则匹配日期和时间(时间戳转换)的实例代码
如何快速生成橙子建站落地页链接?
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
简历在线制作网站免费版,如何创建个人简历?
如何通过商城自助建站源码实现零基础高效建站?
外汇网站制作流程,如何在工商银行网站上做外汇买卖?
整人网站在线制作软件,整蛊网站退不出去必须要打我是白痴才能出去?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
佛山网站制作系统,佛山企业变更地址网上办理步骤?
网站制作知乎推荐,想做自己的网站用什么工具比较好?
微信h5制作网站有哪些,免费微信H5页面制作工具?
建站之星安装模板失败:服务器环境不兼容?
,如何利用word制作宣传手册?
建站之星导航配置指南:自助建站与SEO优化全解析
济南网站制作的价格,历城一职专官方网站?
C#如何使用XPathNavigator高效查询XML
南阳网站制作公司推荐,小学电子版试卷去哪里找资源好?
建站上市公司网站建设方案与SEO优化服务定制指南
惠州网站建设制作推广,惠州市华视达文化传媒有限公司怎么样?
如何基于PHP生成高效IDC网络公司建站源码?
建站之星展会模板:智能建站与自助搭建高效解决方案
建站主机选哪家性价比最高?
建站之星如何防范黑客攻击与数据泄露?
招贴海报怎么做,什么是海报招贴?
Dapper的Execute方法的返回值是什么意思 Dapper Execute返回值详解
如何快速启动建站代理加盟业务?
php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】
如何在橙子建站中快速调整背景颜色?
微信网站制作公司有哪些,民生银行办理公司开户怎么在微信网页上查询进度?
建站主机解析:虚拟主机配置与服务器选择指南
Android自定义listview布局实现上拉加载下拉刷新功能
网站制作的步骤包括,正确网址格式怎么写?
零基础网站服务器架设实战:轻量应用与域名解析配置指南
*服务器网站为何频现安全漏洞?
深圳网站制作平台,深圳市做网站好的公司有哪些?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
如何快速上传建站程序避免常见错误?
可靠的网站设计制作软件,做网站设计需要什么样的电脑配置?
建站之星安装后如何配置SEO及设计样式?
猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?
青岛网站建设如何选择本地服务器?
如何在Tomcat中配置并部署网站项目?
深圳网站制作培训,深圳哪些招聘网站比较好?
保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?
*请认真填写需求信息,我们会在24小时内与您取得联系。