写了一个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

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title>    <style>        .chat{            width: 300px;            height: 500px;            text-align: center;            margin: 0 auto;            border: 1px solid #ccc;        }        .message{            width: 100%;            height: 460px;        }        #table{            border: 1px solid        }    </style></head><body>    <div class="chat">        <select name="" id="select" onchange="console.log()">                    </select>        <div class="message"></div>        <div>我是<span id="_id"></span></div>        <input id="text" type="text" placeholder="请输入聊天信息">        <button onclick="chat()">发送信息</button>    </div>    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>    <!-- 这里socket不需要引用外部文件,node后台运行会自动生成可以引用的js文件 -->    <!-- <script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script> -->    <script src="/socket.io/socket.io.js"></script>    <!-- <script src="./javascripts/underscore.min.js"></script> -->    <script>        let message = document.getElementsByClassName('message')[0]        let socket = io.connect('http://localhost:3000');        //        let userid = this.getUuid()        let userLs = []        socket.emit('login', userid);        //从服务端接收数据        socket.on('login',function (data) {            document.getElementById("_id").innerHTML = data;        })        socket.on('message',function (data) {            message.innerHTML += `${data.id}:${data.message}` + '<br>';        })        socket.on('sayTo',function (data) {            message.innerHTML += `${data.id}:${data.message}` + '<br>';        })        socket.on('userLs',function (data) {            console.log(data)            $("#select").append(`<option value="">所有人</option>`)            if(data.length > 0){                for(let item of data){                    $("#select").append(`<option value="${item.id}">${item.id}</option>`)                }            }        })        socket.on('error', function(msg) {            //错误提示                 alert(msg)             });        function chat(){            let text = document.getElementById('text').value            if(!text){                alert('不能发送空消息!')                return            }            //向服务端发送数据            if($('#select option:selected').val()){                console.log($('#select option:selected').val())                // return                socket.emit('sayTo', {id:$('#select option:selected').val(),message:text});            }else{                socket.emit('message', {message:text});            }        }        function getUuid () {            function S4 () {                return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)            }            return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4())        }    </script></body></html>