socketio
写了一个socket.io服务,实现了用户区分、公聊、私聊等。。。码云地址https://gitee.com/liuoomei/so... app.js //app.jsvar express = require('express')var app = express();var server = require('http').Server(app);// var io = require('socket.io')(server);var path = require('path');app.use(express.static(path.join(__dirname, 'public')))app.get('/', function(req, res){ res.sendFile(path.join(__dirname, 'index.html'));});module.exports = app;bin/www #!/usr/bin/env node/** * Module dependencies. */let app = require('../app');let debug = require('debug')('mysocket:server');let http = require('http');let _ = require('underscore');/** * Get port from environment and store in Express. */let userLs = []let port = normalizePort(process.env.PORT || '3000');app.set('port', port);/** * Create HTTP server. */let server = http.createServer(app);/** * Listen on provided port, on all network interfaces. */server.listen(port);let io = require('socket.io')(server);io.on('connection', function(socket){ socket.on('login', function(userid){ let obj = { userid, id: socket.id } userLs.push(obj) console.log(userid + '建立了链接'); socket.emit('userLs',userLs) socket.emit('login',socket.id) }); // 判断用户离线事件可以通过socket.io自带的disconnect事件完成,当一个用户断开连接,disconnect事件就会触发 socket.on('disconnect', function(){ let _user = _.where(userLs,{id:socket.id}) console.log('_user',_user) console.log(socket.id + '中断了链接'); userLs = userLs.filter(it =>{ return _user.every(item =>{ return it.id != item.id }) }) // do somethings console.log('del',userLs) }); socket.on('message', function (data) { //服务端像所以也没发送数据 let _user = _.where(userLs,{id:socket.id}) io.sockets.emit('message', {id:_user[0].id,userid:_user[0].userid,message:data.message}); //给所有人(包括自己)发送消息 // socket.broadcast.emit('message', data.message); //给所有人(不包括自己)发送消息 }); socket.on('sayTo', function (data) { let toMsg = data.message; let toId = data.id; // nodejs的underscore扩展中的findWhere方法,可以在对象集合中,通过对象的属性值找到该对象并返回。 let _user = _.where(userLs,{id:toId}) if(_user){ let toSocket = _.findWhere(io.sockets.sockets, {id: toId}); // 通过该连接对象(toSocket)与链接到这个对象的客户端进行单独通信 socket.emit('message', {id:socket.id,message:toMsg}) //向建立该连接的客户端广播 toSocket.emit('message', {id:socket.id,message:toMsg}); }else{ socket.emit('error','该用户不在线') } // socket.emit() :向建立该连接的客户端广播 // socket.broadcast.emit() :向除去建立该连接的客户端的所有客户端广播 // io.sockets.emit() : 向所有客户端广播,等同于上面两个的和 });});server.on('error', onError);server.on('listening', onListening);/** * Normalize a port into a number, string, or false. */function normalizePort(val) { let port = parseInt(val, 10); if (isNaN(port)) { // named pipe return val; } if (port >= 0) { // port number return port; } return false;}/** * Event listener for HTTP server "error" event. */function onError(error) { if (error.syscall !== 'listen') { throw error; } let bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port; // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges'); process.exit(1); break; case 'EADDRINUSE': console.error(bind + ' is already in use'); process.exit(1); break; default: throw error; }}/** * Event listener for HTTP server "listening" event. */function onListening() { let addr = server.address(); let bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port; debug('Listening on ' + bind); console.log(`服务已启动,端口:${addr.port}`)}public/index.html ...