基于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的实时在线选座系统相关推荐

  1. 基于PHP的电影订票选座系统

    有需要请私信或看评论链接哦 可远程调试 基于PHP的电影订票选座系统 一 介绍 此电影订票选座系统基于原生PHP开发,数据库mysql,前端jquery.js.系统角色分为用户和管理员.用户注册登录后 ...

  2. jQuery在线选座系统(高铁版)

    除了电影院在线选座,我们还会接触到飞机机舱选座,当然也有汽车票火车票选座的.假如有一天买火车票也提供在线选座,那么今天我来给大家介绍下如何使用jQuery选座插件完成高铁列车座位布置.选座.不同等级座 ...

  3. 基于 socket.io 实现实时你画我猜游戏

    前言 一直都想好好的学习运用node,一直都不知道要做什么东西,最近Java Web老师要求做个前端的应用,既然是前端应用,那肯定得是单页应用了,而且node很适用于高并发的实时应用,所以便选择nod ...

  4. php 在线选座,捷西网络在线选座系统

    PHP源码结构 该系统用Yii Framework开发,源码结构如下: 根目录/ assets 存放CSS.js等前端资源的目录 css 存放css文件 documentation 网站使用说明文档 ...

  5. 基于微信小程序的图书馆选座系统源码

    开发环境及工具: 大等于jdk1.8,大于mysql5.5,idea(eclipse),微信开发者工具 技术说明: springboot mybatis 小程序 代码注释齐全,没有多余代码,适合学习( ...

  6. java基于ssm的电影院订票选座系统

    技术:ssm+mysql+eclipse+tomcat+java 截图: 部分数据库: CREATE TABLE allusers ( id int(11) NOT NULL AUTO_INCREME ...

  7. 毕业设计-基于微信小程序的图书馆选座系统

    目录 前言 课题背景与简介 实现设计思路 一.系统分析及功能设计 二.学生端系统详细设计 三.系统测试与结构分析 四.总结 实现效果样例 更多帮助 前言

  8. 软件工程毕业设计课题(20)基于JAVA毕业设计在线选座购票电影院网站系统毕设作品项目

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于java的电影院订票选座系统,系统整体使用了基于java+MySql的B/S架构,技术上使用了springboot框架:使用浏览器,管理员通 ...

  9. 计算机毕业设计(20)java毕设作品之电影院在线选座售票系统

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于java的电影院订票选座系统,系统整体使用了基于java+MySql的B/S架构,技术上使用了springboot框架:使用浏览器,管理员通 ...

最新文章

  1. 2014-01-04 SQL练习
  2. Detectron2 win10踩坑记录
  3. 文字加减前后缀lisp_LISP 图层前后缀_显示图层的Lisp程式
  4. 给Eclipse在线安装WTP
  5. 麦克风阵列原理(转载)
  6. dblink连接远程mysql_MySQL中使用federated 实现dblink 远程表访问
  7. 器件选型电源篇-LDO器件选型
  8. 无线PLC专用数据终端应用方案
  9. 开发实战:舍得网44587行代码开发经验
  10. Vue解决跨域问题之Node反向代理
  11. 笔记本电脑桌面便签哪个软件好用,桌面便签软件下载
  12. BUUCTF:[XMAN2018排位赛]通行证
  13. Delphi取整函数
  14. 数列分块入门练习题一
  15. 绕过知乎网页版禁止转载限制进行复制
  16. 还在熬夜干论文——Python带你一键起飞!【内附演示视频】
  17. deployer php,deployer 实战经验分享
  18. 【性能策略】限流策略
  19. 关于onMeasure(转载)
  20. 《大学四年》——知乎 读书笔记

热门文章

  1. 网站图标favicon.ico
  2. 汽车ECU通信相关验证项有哪些?
  3. Explaindio Video Creator Platinum(简称EVC) 3.042 Windows中文白金版MG动画2D和3D动画解说动画手绘白板动画视频制作软件
  4. 百度SEO站群在线做横幅banner广告源码
  5. JS二进制和十六进制转换
  6. python数学运算练习
  7. python头像右上角加红色数字_将你的 QQ 头像(或者微博头像)右上角加上红色的数字,类似于微信未读信息数量那种提示效果...
  8. [Python][CV2]cv2.imwrite写jpg图像会引入噪声
  9. 华为笔记本 Win10+Deepin 双系统安装方法
  10. 刘谦2010春晚魔术解密