├── README.md ├── app.js ├── doc ├── 1508489067(1).png └── 1508489279(1).png ├── package.json └── www ├── css └── index.css ├── index.html └── js ├── index.js └── socket.io.js /README.md: -------------------------------------------------------------------------------- 1 | # express-socket 2 | > express+socket.io聊天室 3 | 4 | #### 完成 5 | - [x] 登陆提醒 6 | - [x] 退出提醒 7 | - [x] 在线聊天 8 | - [x] 在线人数统计 9 | 10 | #### todo 11 | - [ ] 多个房间 12 | - [ ] 单独聊天 13 | - [ ] 头像 14 | 15 | ## 项目大概 16 | 17 | .png) 18 | .png) 19 | 20 | ## 安装运行 21 | ``` 22 | git clone https://github.com/pengrongjie/express-socket.git 23 | cd express-socket 24 | cnpm install 25 | node app.js 26 | ``` 27 | > http://localhost:80/ 28 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var app = express(); 3 | var server = require('http').createServer(app); 4 | var io = require('socket.io').listen(server); 5 | // 存储用户 6 | var users = []; 7 | 8 | app.use('/',express.static(__dirname + '/www')); 9 | server.listen(80); 10 | console.log("http://localhost:80/"); 11 | 12 | // socket.io 13 | 14 | io.on('connection', function(socket){ 15 | // 登录 16 | socket.on('login', function(nickname){ 17 | if(users.indexOf(nickname) > -1){ 18 | socket.emit('loginFailed'); 19 | }else{ 20 | socket.nickname = nickname; 21 | users.push(nickname); 22 | console.log(nickname + '已经上线了,总在线人数为:' + users.length); 23 | socket.emit('loginSuccess'); 24 | io.sockets.emit('system', nickname, users.length, 'login'); 25 | } 26 | }) 27 | 28 | //断开连接,实时更新users数组 29 | socket.on('disconnect', function(){ 30 | var index = users.indexOf(socket.nickname); 31 | users.splice(index, 1); 32 | io.sockets.emit('system', socket.nickname, users.length, 'logout'); 33 | console.log(socket.nickname + '已经下线了'); 34 | console.log(users); 35 | }) 36 | // 发送消息 37 | socket.on('msgSend', function(msg){ 38 | socket.broadcast.emit('newMsg', socket.nickname, msg); 39 | }) 40 | }) 41 | -------------------------------------------------------------------------------- /doc/1508489067(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengrongjie/express-socket/6032259179cd2294f0635ca7e73be543cf64a148/doc/1508489067(1).png -------------------------------------------------------------------------------- /doc/1508489279(1).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pengrongjie/express-socket/6032259179cd2294f0635ca7e73be543cf64a148/doc/1508489279(1).png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "socket7ss", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "express": "^4.16.2", 13 | "socket.io": "^2.0.3" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /www/css/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | ul { 6 | list-style: none; 7 | } 8 | a { 9 | text-decoration: none; 10 | } 11 | button, 12 | input { 13 | outline: none; 14 | } 15 | body { 16 | padding: 50px 0; 17 | background-color: #f1f1f1; 18 | } 19 | /*头部*/ 20 | body .header { 21 | position: fixed; 22 | top: 0; 23 | left: 0; 24 | height: 50px; 25 | width: 100%; 26 | text-align: center; 27 | line-height: 50px; 28 | color: #fff; 29 | background-color: #00aaee; 30 | z-index: 999; 31 | } 32 | /*登录框*/ 33 | body .loginWrapper{ 34 | position: fixed; 35 | top: 0; 36 | left: 0; 37 | bottom: 0; 38 | right: 0; 39 | text-align: center; 40 | padding-top: 40%; 41 | background-color: rgba(0,0,0,.1); 42 | z-index: 1000; 43 | } 44 | body .loginWrapper .info{ 45 | height: 50px; 46 | line-height: 50px; 47 | } 48 | body .loginWrapper input{ 49 | display: block; 50 | height: 40px; 51 | width: 80%; 52 | line-height: 40px; 53 | margin: 20px auto; 54 | text-align: center; 55 | border: 1px solid #ccc; 56 | border-radius: 4px; 57 | } 58 | body .loginWrapper input:focus{ 59 | border: 1px solid #00aaee; 60 | } 61 | body .loginWrapper input.button{ 62 | background-color: #00aaee; 63 | color: #fff; 64 | } 65 | /*输入框*/ 66 | body .control{ 67 | position: fixed; 68 | display: flex; 69 | bottom: 0; 70 | left: 0; 71 | width: 100%; 72 | height: 40px; 73 | z-index: 1000; 74 | } 75 | body .control input { 76 | flex: 1; 77 | padding-left: 10px; 78 | background-color: #fff; 79 | border: 1px solid #ccc; 80 | border-radius: 4px; 81 | } 82 | body .control input:focus{ 83 | border: 1px solid #00aaee; 84 | } 85 | body .control button{ 86 | flex: 0 0 60px; 87 | width: 60px; 88 | background-color: #00aaee; 89 | color: #fff; 90 | border: 1px solid #00aaee; 91 | border-radius: 4px; 92 | } 93 | /*系统消息*/ 94 | body .historyMsg{ 95 | 96 | } 97 | body .historyMsg .system{ 98 | height: 40px; 99 | line-height: 40px; 100 | text-align: center; 101 | } 102 | body .historyMsg .system .nickname{ 103 | color: #00aaee; 104 | } 105 | /*我自己发送的消息*/ 106 | body .historyMsg .myMsg { 107 | margin: 0 10px 10px 0; 108 | text-align: right; 109 | } 110 | body .historyMsg .myMsg .timespan{ 111 | display: block; 112 | font-size: 12px; 113 | color: #333; 114 | } 115 | body .historyMsg .myMsg .nickname{ 116 | display: none; 117 | } 118 | body .historyMsg .myMsg .text{ 119 | display: inline-block; 120 | height: 30px; 121 | line-height: 30px; 122 | margin-top: 5px; 123 | padding: 0 8px; 124 | background-color: #00aaee; 125 | color: #fff; 126 | border: 1px solid #00aaee; 127 | border-radius: 10px; 128 | } 129 | 130 | /*别人发送的消息*/ 131 | body .historyMsg .newMsg{ 132 | margin: 0 0 10px 10px; 133 | } 134 | body .historyMsg .newMsg .timespan{ 135 | display: block; 136 | font-size: 12px; 137 | color: #333; 138 | } 139 | body .historyMsg .newMsg .nickname{ 140 | display: inline-block; 141 | height: 30px; 142 | line-height: 30px; 143 | margin-top: 5px; 144 | padding: 0 4px; 145 | background-color: #fff; 146 | color: #00aaee; 147 | border: 1px solid #fff; 148 | border-radius: 10px 0 0 10px;; 149 | } 150 | body .historyMsg .newMsg .text{ 151 | display: inline-block; 152 | height: 30px; 153 | line-height: 30px; 154 | margin-top: 5px; 155 | padding: 0 4px 0 4px; 156 | background-color: #fff; 157 | color: #333; 158 | border: 1px solid #fff; 159 | border-radius: 0 10px 10px 0; 160 | } 161 | .nickWrapper{ 162 | display: none; 163 | } 164 | -------------------------------------------------------------------------------- /www/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 |欢迎来到express+socket聊天室
30 |kyrieliu加入了群聊
175 | var p = document.createElement('p'); 176 | var span = document.createElement('span'); 177 | var text; 178 | if (type == 'login'){ 179 | text = document.createTextNode(' 加入了群聊'); 180 | }else if (type == 'logout'){ 181 | text = document.createTextNode(' 离开了群聊'); 182 | } 183 | 184 | p.setAttribute('class','system'); 185 | span.setAttribute('class','nickname'); 186 | span.textContent = nickname; 187 | 188 | p.appendChild(span); 189 | p.appendChild(text); 190 | 191 | 192 | historyMsg.appendChild(p); 193 | } 194 | 195 | }; 196 | -------------------------------------------------------------------------------- /www/js/socket.io.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.io=e():t.io=e()}(this,function(){return function(t){function e(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return t[r].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var n={};return e.m=t,e.c=n,e.p="",e(0)}([function(t,e,n){"use strict";function r(t,e){"object"===("undefined"==typeof t?"undefined":o(t))&&(e=t,t=void 0),e=e||{};var n,r=i(t),s=r.source,u=r.id,h=r.path,f=p[u]&&h in p[u].nsps,l=e.forceNew||e["force new connection"]||!1===e.multiplex||f;return l?(c("ignoring socket cache for %s",s),n=a(s,e)):(p[u]||(c("new io instance for %s",s),p[u]=a(s,e)),n=p[u]),r.query&&!e.query&&(e.query=r.query),n.socket(r.path,e)}var o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},i=n(1),s=n(7),a=n(13),c=n(3)("socket.io-client");t.exports=e=r;var p=e.managers={};e.protocol=s.protocol,e.connect=r,e.Manager=n(13),e.Socket=n(39)},function(t,e,n){(function(e){"use strict";function r(t,n){var r=t;n=n||e.location,null==t&&(t=n.protocol+"//"+n.host),"string"==typeof t&&("/"===t.charAt(0)&&(t="/"===t.charAt(1)?n.protocol+t:n.host+t),/^(https?|wss?):\/\//.test(t)||(i("protocol-less url %s",t),t="undefined"!=typeof n?n.protocol+"//"+t:"https://"+t),i("parse %s",t),r=o(t)),r.port||(/^(http|ws)$/.test(r.protocol)?r.port="80":/^(http|ws)s$/.test(r.protocol)&&(r.port="443")),r.path=r.path||"/";var s=r.host.indexOf(":")!==-1,a=s?"["+r.host+"]":r.host;return r.id=r.protocol+"://"+a+":"+r.port,r.href=r.protocol+"://"+a+(n&&n.port===r.port?"":":"+r.port),r}var o=n(2),i=n(3)("socket.io-client:url");t.exports=r}).call(e,function(){return this}())},function(t,e){var n=/^(?:(?![^:@]+:[^:@\/]*@)(http|https|ws|wss):\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?((?:[a-f0-9]{0,4}:){2,7}[a-f0-9]{0,4}|[^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/,r=["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"];t.exports=function(t){var e=t,o=t.indexOf("["),i=t.indexOf("]");o!=-1&&i!=-1&&(t=t.substring(0,o)+t.substring(o,i).replace(/:/g,";")+t.substring(i,t.length));for(var s=n.exec(t||""),a={},c=14;c--;)a[r[c]]=s[c]||"";return o!=-1&&i!=-1&&(a.source=e,a.host=a.host.substring(1,a.host.length-1).replace(/;/g,":"),a.authority=a.authority.replace("[","").replace("]","").replace(/;/g,":"),a.ipv6uri=!0),a}},function(t,e,n){(function(r){function o(){return!("undefined"==typeof window||!window.process||"renderer"!==window.process.type)||("undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/))}function i(t){var n=this.useColors;if(t[0]=(n?"%c":"")+this.namespace+(n?" %c":" ")+t[0]+(n?"%c ":" ")+"+"+e.humanize(this.diff),n){var r="color: "+this.color;t.splice(1,0,r,"color: inherit");var o=0,i=0;t[0].replace(/%[a-zA-Z%]/g,function(t){"%%"!==t&&(o++,"%c"===t&&(i=o))}),t.splice(i,0,r)}}function s(){return"object"==typeof console&&console.log&&Function.prototype.apply.call(console.log,console,arguments)}function a(t){try{null==t?e.storage.removeItem("debug"):e.storage.debug=t}catch(n){}}function c(){var t;try{t=e.storage.debug}catch(n){}return!t&&"undefined"!=typeof r&&"env"in r&&(t=r.env.DEBUG),t}function p(){try{return window.localStorage}catch(t){}}e=t.exports=n(5),e.log=s,e.formatArgs=i,e.save=a,e.load=c,e.useColors=o,e.storage="undefined"!=typeof chrome&&"undefined"!=typeof chrome.storage?chrome.storage.local:p(),e.colors=["lightseagreen","forestgreen","goldenrod","dodgerblue","darkorchid","crimson"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(e){return"[UnexpectedJSONParseError]: "+e.message}},e.enable(c())}).call(e,n(4))},function(t,e){function n(){throw new Error("setTimeout has not been defined")}function r(){throw new Error("clearTimeout has not been defined")}function o(t){if(u===setTimeout)return setTimeout(t,0);if((u===n||!u)&&setTimeout)return u=setTimeout,setTimeout(t,0);try{return u(t,0)}catch(e){try{return u.call(null,t,0)}catch(e){return u.call(this,t,0)}}}function i(t){if(h===clearTimeout)return clearTimeout(t);if((h===r||!h)&&clearTimeout)return h=clearTimeout,clearTimeout(t);try{return h(t)}catch(e){try{return h.call(null,t)}catch(e){return h.call(this,t)}}}function s(){y&&l&&(y=!1,l.length?d=l.concat(d):m=-1,d.length&&a())}function a(){if(!y){var t=o(s);y=!0;for(var e=d.length;e;){for(l=d,d=[];++m0;){for(var s=new Uint8Array(o),a=0===s[0],c="",p=1;255!==s[p];p++){if(c.length>310)return r(w,0,1);c+=s[p]}o=f(o,2+c.length),c=parseInt(c);var u=f(o,0,c);if(a)try{u=String.fromCharCode.apply(null,new Uint8Array(u))}catch(h){var l=new Uint8Array(u);u="";for(var p=0;p