基于socket.io的实时在线选座系统
基于socket.io的实时在线选座系统(demo)
前言
前段时间公司做一个关于剧院的项目,遇到了这样一种情况。
在高并发多用户同时选座的情况下,假设A用户进入选座页面,正在选择座位,此时还没有提交所选择的座位。
这时B用户进入选座页面,迅速的选择了座位,提交。
而这个时候,A终于选择完毕,提交。 发现座位已经被买了。
当用户越多这样的情况越严重。
具体场景就是如此。
1、简介
本项目是基于jquery.seat-charts在线选座插件。集合socket.io,实现的实时选座系统,可应用于剧院,影院,车票等!
Socket.IO是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它主要是为了实现客户端和服务端的全双工通信。我们传统的http请求(抛开长链接不谈),只实现了一请求一回复的,没有办法做到服务器端向客户端推送数据的情况。而Socket.IO则实现了这一点。
依赖的模块
- node.js
- express
- socket.io
- jquery.seat-charts
2、安装部署
2.1 部署 express服务器
express是一个小巧的Node.js的Web应用框架,在构建HTTP服务器时经常使用到,所以直接以Socket.IO和express为例子来讲解。
在node.js环境下
npm install express express XXX *(XXX)是你的项目名字*cd XXX *进入你的项目*npm install *下载依赖*
2.2 添加依赖模块、修改默认的express框架
本项目没有使用express默认的模板引擎jade,采用了ejs模板,对新手来说更友好,学习成本更低。
npm install -D socket.io ejs
虽然简单,但是如果使用在express框架上则需要修改以下几个位置。
> views目录下所有文件
改为ejs后缀。 并把内容改为标准html 5 模板。
app.js 文件
app.set('view engine', 'jade');
修改为 ==> app.set('view engine', 'ejs');
bin > www 文件
因为socket.io需要监听服务,所以我们需要把www文件中的server 抛出
module.exports = server; 添加在www文件最后一行即可
新建 bin > socket.js 文件 (后续添加该处代码)
放置socket.io核心代码。实现模块分离。
bin > www 放置服务配置
bin > socket.js 放置socket.io配置信息
package.json 修改入口配置
"scripts": {"start": "node ./bin/www"
}
修改为
"scripts": {"start": "node ./bin/socket.js"
}
3、服务端代码
bin > socket.js
var server = require("./www");
var io = require("socket.io")(server);io.chooseSeat = {};io.on('connection', function(socket) {//用户选择的座位socket.chooseSeat = {};socket.isSold = false;socket.on('login', function(data) {io.emit("loginlock",io.chooseSeat);});//监听用户选择座位socket.on('selected', function(data) {socket.chooseSeat[data.id] = data;io.chooseSeat[data.id] = data;io.emit("locking",data);});socket.on('cancleselected', function(data) {delete socket.chooseSeat[data.id];delete io.chooseSeat[data.id];io.emit("canclelocking",data)});socket.on('sold', function(data) {// 把售卖的座位信息返给其他用户socket.isSold = trueio.emit('seatsold', Object.keys(data));});//监听用户退出 释放用户选择的未提交座位socket.on('disconnect', function() {// 如果没有购买,直接就退出了,才去释放座位for(var t in socket.chooseSeat){delete io.chooseSeat[t];}if (!socket.isSold) {io.emit('userout', socket.chooseSeat);}})
});
4、客户端代码
bin > socket.js
<!DOCTYPE html>
<html lang="en">
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>基于socket.io的实时在线选座系统(影院版)</title><meta name="keywords" content="jQuery在线选座,jQuery选座系统,WebSocket,socket.io,实时选座系统" /><meta name="description" content="本项目是基于jquery.seat-charts在线选座插件。集合socket.io,实现的实时选座系统,可应用于剧院,影院,车票等" /><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><link rel="stylesheet" type="text/css" href="css/reset.css" /><link rel="stylesheet" type="text/css" href="css/index.css" />
</head>
<body><div class="container"><h2 class="title"><a href="#">jQuery在线选座(影院版)</a></h2><div class="demo clearfix"><!---左边座位列表--><div id="seat_area"><div class="front">屏幕</div></div><!---右边选座信息--><div class="booking_area"><p>电影:<span>天将雄师</span></p><p>时间:<span>03月20日 22:15</span></p><p>座位:</p><ul id="seats_chose"></ul><p>票数:<span id="tickects_num">0</span></p><p>总价:<b>¥<span id="total_price">0</span></b></p><input type="button" class="btn" id="commitSeat" value="确定购买" /><div id="legend"></div></div></div></div> <script src="js/jquery-3.2.1.js"></script><script src="/socket.io/socket.io.js"></script><script src="js/jquery.seat-charts.js"></script><script src="js/index.js"></script>
</body>
</html>
pulic > js > index.js
$(function(){var price = 100; //电影票价var initData = {socket: io.connect('http://192.168.1.96:3000'),mapData:[ //座位结构图 a 代表座位; 下划线 "_" 代表过道'cccccccccc','cccccccccc','__________','cccccccc__','cccccccccc','cccccccccc','cccccccccc','cccccccccc','cccccccccc','cc__cc__cc'],iconStatus:[ // 座位状态['c', 'available', '可选座'],['c', 'selected', '已选中'],['c', 'locking', '已锁定'],['c', 'unavailable', '已售出'],],selectedSeat:{} }var interaction = {initMap:function(){var _this = this;var $cart = $('#seats_chose'), //座位区$tickects_num = $('#tickects_num'), //票数$total_price = $('#total_price'); //票价总额var sc = $('#seat_area').seatCharts({map:initData.mapData,naming: { //设置行列等信息top: false, //不显示顶部横坐标(行) getLabel: function(character, row, column) { //返回座位信息 return column;}},legend: { //定义图例node: $('#legend'),items: initData.iconStatus},click: function() {if (this.status() == 'available') { //若为可选座状态,添加座位$('<li>' + (this.settings.row + 1) + '排' + this.settings.label + '座</li>').attr('id', 'cart-item-' + this.settings.id).data('seatId', this.settings.id).appendTo($cart);$tickects_num.text(sc.find('selected').length + 1); //统计选票数量$total_price.text(_this.getTotalPrice(sc) + price); //计算票价总金额// 向服务器发送消息,座位被我选中_this.emit("selected",{firetype:'selected',firetime:new Date().toLocaleString(),character:this.settings.character,column:this.settings.column,data:this.settings.data,id:this.settings.id,label:this.settings.label,row:this.settings.row})initData.selectedSeat[this.settings.id] = this.settings;return 'selected';} else if (this.status() == 'selected') { //若为选中状态$tickects_num.text(sc.find('selected').length - 1); //更新票数量$total_price.text(_this.getTotalPrice(sc) - price); //更新票价总金额$('#cart-item-' + this.settings.id).remove(); //删除已预订座位// 向服务器发送消息,座位被我取消_this.emit("cancleselected",{firetype:'cancleselected',firetime:new Date().toLocaleString(),character:this.settings.character,column:this.settings.column,data:this.settings.data,id:this.settings.id,label:this.settings.label,row:this.settings.row})delete initData.selectedSeat[this.settings.id];return 'available';} else if (this.status() == 'unavailable') { //若为已售出状态return 'unavailable';} else {return this.style();}}});//设置已售出的座位sc.get(['1_3', '1_4', '4_4', '4_5', '4_6', '4_7', '4_8']).status('unavailable'); interaction.commitSeat();},getTotalPrice:function(sc){//计算票价总额var total = 0;sc.find('selected').each(function() {total += price;});return total;},emit:function(type,msg){initData.socket.emit(type,msg); },socketEvent:function(){this.emit("login","用户进入选座页面"); initData.socket.on("loginlock",function(loginlock){for(var t in loginlock){var isMine = interaction.isMineFire(t,"selected");if (!isMine) {$('#'+t).addClass("locking"); }} })initData.socket.on("locking",function(data){var isMine = interaction.isMineFire(data.id,"selected");if (!isMine) {$('#'+data.id).addClass("locking")}})initData.socket.on("canclelocking",function(data){$('#'+data.id).removeClass("locking"); })initData.socket.on("userout",function(outuser){// outuser 为退出用户所选择的座位。for(var t in outuser){$('#'+t).removeClass("locking"); }})initData.socket.on("seatsold",function(soldseat){// soldseat 为用户已经购买的座位。 客户端更新座位状态$.each(soldseat,function(index,item){$('#'+item).addClass('unavailable');})}) },isMineFire:function(id,type){return $('#'+id).attr('class').indexOf(type) > 0;},commitSeat:function(){$("#commitSeat").click(function(){if (JSON.stringify(initData.selectedSeat) === "{}") {alert("请至少选择一个座位再提交!")return false;}//$.post("http://XXXXXXXX",座位数据,function(){// 延迟2秒模拟生成订单的ajax请求,请求成功跳转订单页。setTimeout(function() {interaction.emit("sold",initData.selectedSeat);location.href = "/order";}, 2000);//})})}}interaction.initMap();interaction.socketEvent();
})
5、查看效果
打开浏览器,输入localhost:3000
多打开几个浏览器,可查看实时响应效果
6、注意事项
此处需要修改为你自己的端口,否则会出现监听不到的情况。
作者 HoChine
2017 年 09月 03日
项目演示: http://hochine.cn/demo/realTimeChooseSeat
GitHub地址: https://github.com/HoChine/RealTime-chooseSeat
转载于:https://www.cnblogs.com/HoChine/p/7553236.html
基于socket.io的实时在线选座系统相关推荐
- 基于PHP的电影订票选座系统
有需要请私信或看评论链接哦 可远程调试 基于PHP的电影订票选座系统 一 介绍 此电影订票选座系统基于原生PHP开发,数据库mysql,前端jquery.js.系统角色分为用户和管理员.用户注册登录后 ...
- jQuery在线选座系统(高铁版)
除了电影院在线选座,我们还会接触到飞机机舱选座,当然也有汽车票火车票选座的.假如有一天买火车票也提供在线选座,那么今天我来给大家介绍下如何使用jQuery选座插件完成高铁列车座位布置.选座.不同等级座 ...
- 基于 socket.io 实现实时你画我猜游戏
前言 一直都想好好的学习运用node,一直都不知道要做什么东西,最近Java Web老师要求做个前端的应用,既然是前端应用,那肯定得是单页应用了,而且node很适用于高并发的实时应用,所以便选择nod ...
- php 在线选座,捷西网络在线选座系统
PHP源码结构 该系统用Yii Framework开发,源码结构如下: 根目录/ assets 存放CSS.js等前端资源的目录 css 存放css文件 documentation 网站使用说明文档 ...
- 基于微信小程序的图书馆选座系统源码
开发环境及工具: 大等于jdk1.8,大于mysql5.5,idea(eclipse),微信开发者工具 技术说明: springboot mybatis 小程序 代码注释齐全,没有多余代码,适合学习( ...
- java基于ssm的电影院订票选座系统
技术:ssm+mysql+eclipse+tomcat+java 截图: 部分数据库: CREATE TABLE allusers ( id int(11) NOT NULL AUTO_INCREME ...
- 毕业设计-基于微信小程序的图书馆选座系统
目录 前言 课题背景与简介 实现设计思路 一.系统分析及功能设计 二.学生端系统详细设计 三.系统测试与结构分析 四.总结 实现效果样例 更多帮助 前言
- 软件工程毕业设计课题(20)基于JAVA毕业设计在线选座购票电影院网站系统毕设作品项目
项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于java的电影院订票选座系统,系统整体使用了基于java+MySql的B/S架构,技术上使用了springboot框架:使用浏览器,管理员通 ...
- 计算机毕业设计(20)java毕设作品之电影院在线选座售票系统
项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于java的电影院订票选座系统,系统整体使用了基于java+MySql的B/S架构,技术上使用了springboot框架:使用浏览器,管理员通 ...
最新文章
- 2014-01-04 SQL练习
- Detectron2 win10踩坑记录
- 文字加减前后缀lisp_LISP 图层前后缀_显示图层的Lisp程式
- 给Eclipse在线安装WTP
- 麦克风阵列原理(转载)
- dblink连接远程mysql_MySQL中使用federated 实现dblink 远程表访问
- 器件选型电源篇-LDO器件选型
- 无线PLC专用数据终端应用方案
- 开发实战:舍得网44587行代码开发经验
- Vue解决跨域问题之Node反向代理
- 笔记本电脑桌面便签哪个软件好用,桌面便签软件下载
- BUUCTF:[XMAN2018排位赛]通行证
- Delphi取整函数
- 数列分块入门练习题一
- 绕过知乎网页版禁止转载限制进行复制
- 还在熬夜干论文——Python带你一键起飞!【内附演示视频】
- deployer php,deployer 实战经验分享
- 【性能策略】限流策略
- 关于onMeasure(转载)
- 《大学四年》——知乎 读书笔记
热门文章
- 网站图标favicon.ico
- 汽车ECU通信相关验证项有哪些?
- Explaindio Video Creator Platinum(简称EVC) 3.042 Windows中文白金版MG动画2D和3D动画解说动画手绘白板动画视频制作软件
- 百度SEO站群在线做横幅banner广告源码
- JS二进制和十六进制转换
- python数学运算练习
- python头像右上角加红色数字_将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果...
- [Python][CV2]cv2.imwrite写jpg图像会引入噪声
- 华为笔记本 Win10+Deepin 双系统安装方法
- 刘谦2010春晚魔术解密