行者无忌
新手
新手
  • 最后登录2018-04-17
  • 发帖数3
阅读:8315回复:0

express+socket.io打造实时聊天

楼主#
更多 发布于:2017-05-18 10:36
说点废话:最近公司闲着无聊,做了一个实时聊天。发现bug不断。还好。摸爬滚打一番之后。终于搞定了。后续的功能还在不断完善....
不废话了先上图:

图片:QQ图片20170518110135.png

图片:QQ截图20170518105920.png

图片:QQ截图20170518110822.png


先安装sock.io(express就不多说了)注:socket.io分为服务端和客户端

npm install socket.io

服务端:(先建立express的服务模块在建立socket服务模块)




注意:require('./server/node_modules/socket.io').listen(端口号)和app.set("port",9999);是socket.io和express两个不同的端口号,做不一样的事情。前者监听socket后者express。

這里当初入坑太久。一直找不到原因。

网上很多人写的是io = require('socket.io').listen(app),之前也是一样的這样配置。结果发现端口一样两个电脑根本访问不了。localhost却没有问题。

var express=require('./server/node_modules/express');
var app=express();
var io=require('./server/node_modules/socket.io').listen(3000);

//存储登陆姓名及唯一ID标识 var clientUsers=[];

// 设置服务器端口 app.set("port",9999);

//express 进行配置 app.configure(function(){
        app.use(express.static(__dirname+"/client"));//静态资源文件的路径 }
);

//拦截地址 app.get('/', function(req, res){ res.redirect("index2.html");
});

//监听服务器 app.listen(app.get("port"),function(req,resp){ console.log("请求来了");
});




//监听客户端连接,回调函数会传递本次连接的socket
io.on('connection', function (client) {
    // 接受客户端消息(YourcustomMessage)

client.on('YourcustomMessage', function (data) { console.log('收到客户端消息:', data);
});

// 监听socket断开与重连
client.on('disconnect', function () {
 console.log('你与服务器已经断开连接');
 });

});


客户端:(客户端一个引用了socket.io.js的javscript库
还有就是连接服务器(通过io.connect(‘http://localhost’))
之后在监听收发消息以及广播消息了)

<script src='../js/socket.io.js'></script>引入注意:网上很多人会写localhost:端口号来获取。本人不建议。因为换了端口号忘记更改,后来找Bug会像我一样找本天。而且用IP地址访问一旦端口号不正确就各种错误。反正我是遇到太多。


上代码:

var HTML5WebSockets = {}; HTML5WebSockets.socketio = { yoursocket: null,
        initialize: function () {


            //建立一个socket连接(页面地址http://192.168.1.16:3000)
//            HTML5WebSockets.socketio.yoursocket = io.connect('http://192.168.3.165:3000');這是socket.io客户端的发送的端口号。所以要与服务器
listen(3000);一样 HTML5WebSockets.socketio.yoursocket =io('ws://192.168.3.165:3000', {transports: ['websocket']});

//注:{transports: ['websocket']}很多人都不回加。我也不是为了加了好玩。看了好半天大神的论坛才知道Bug存在的原因。 //连接服务器 HTML5WebSockets.socketio.yoursocket.on('connect', function () { HTML5WebSockets.socketio.log('<p class="link">你好你已成功连接服务器
</p>');
            });


            //[广播消息]接收到服务器的消息(此时服务器为广播消息YourMessageResponse name为服务端获取的名称) HTML5WebSockets.socketio.yoursocket.on('YourMessageResponse', function (data,name) { HTML5WebSockets.socketio.log(); $("#log").scrollTop(9999999);//消息置底 给QQ微信一样。超过屏幕的消息总会在最底下 });
        
            //监听socket断开与重连 HTML5WebSockets.socketio.yoursocket.on('disconnect', function () { HTML5WebSockets.socketio.log('<p class="off">你与服务器断开连接</p>
');
            });

            //监听关闭客户端退出聊天(YouDisconnect) HTML5WebSockets.socketio.yoursocket.on('YouDisconnect',  function (data) { HTML5WebSockets.socketio.log('<p class="off">***退出了聊天</p>
');
            });

            //处理DOM元素 document.querySelector('#sendCustMes').onclick = function () { HTML5WebSockets.socketio.emitCustomMessageToServer(document.querySelector('#custMes').value); document.querySelector('#custMes').value = '';
            };
//            $(document).keydown(function (event) {
//                switch (event.keyCode) {
//                    case 13://回车处理DOM元素 //                    HTML5WebSockets.socketio.emitCustomMessageToServer(document.querySelector('#custMes').value);
//                    document.querySelector('#custMes').value = '';
//                    break;
//                }
//                return false;
//            });

        },

        //客户端发送消息到服务器(YourcustomMessage)客户端服务端 emitCustomMessageToServer: function (data) {
            //客户端自己发的消息 HTML5WebSockets.socage">
ketio.log();

HTML5WebSockets.socketio.yoursocket.emit('YourcustomMessage', data,name);
        }, log: function (message) { document.querySelector('#log').innerHTML += message;
        },
    }




<div id='log'></div>

<div class="btn">
    <input type='text' id='custMes' />
    <button type='button' id='sendCustMes'>&#xe68c;</button>
</div>


完整代码:

服务端:


var express=require('./server/node_modules/express');
var app=express();
var io=require('./server/node_modules/socket.io').listen(3000);

//存储登陆姓名及唯一ID标识 var clientUsers=[];

// 设置服务器端口 app.set("port",9999);

//express 进行配置 app.configure(function(){
        app.use(express.static(__dirname+"/client"));//静态资源文件的路径 }
);

//拦截地址 app.get('/', function(req, res){ res.redirect("index2.html");
});

//监听服务器 app.listen(app.get("port"),function(req,resp){ console.log("请求来了");
});

//监听客户端连接,回调函数会传递本次连接的socket
io.on('connection', function (client) {

    // 接受客户端消息(YourcustomMessage) client.on('YourcustomMessage', function (data,name) { console.log('收到客户端消息:', data,name);
        //给所有客户端发出广播消息emit(发送YourMessageResponse)服务端客户端 client.broadcast.emit('YourMessageResponse', data ,name);
    });

    // 接受客户端消息(YourcustomMessage_1,登陆姓名)
    //YourcustomMessage_1 实时消息 client.on('YourcustomMessage_1', function (name_1) { console.log('收到客户端姓名:',name_1);
        //为了获取客户端传过来的登陆姓名(name_1是全部姓名信息不能作为单个退出记录)
        clientUsers.push({"ClientID":client.id,"UserName":name_1}); client.broadcast.emit('YourMessageResponse_1',name_1);
    });

    // 监听socket断开与重连 client.on('disconnect', function () { console.log('你与服务器已经断开连接');
        //clientID(socket.io会在断开连接时用client.id作为唯一标识)
        var clientID=client.id;
        var userName='';
        var index=0;
        //当数组内的ClientID({"ClientID":client.id})==断开时唯一记录的标识  就取userName(***退出了聊天)取出唯一标识的姓名 for(index;index<clientUsers.length;index++){
            if(clientUsers[index].ClientID==clientID){
                userName=clientUsers[index].UserName;
                break;
            }
        } client.broadcast.emit('YouDisconnect',userName); console.log(userName,'退出了聊天');

        //清空退出聊天的客户端信息 clientUsers.splice(index, 1);
    });

});



客户端

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="format-detection" content="telephone=no"/>
    <meta name="format-detection" content="email=no"/>
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" name="viewport">
    <title>聊天测试demo</title>
    <link rel="stylesheet" href="../css/index2.css">
    <!--<link rel="stylesheet" type="text/css" href="./style.css" />-->

    <!--IE8以下版本的IE浏览器中加载,目的是让这些低版本的IE浏览器也能处理json,这是一个开源的JS,详见:http://bestiejs.github.io/json3/-->
    <!--[if lt IE 8]><script src="./json3.min.js"></script><![endif]-->

    <!--Socket.IO提供的客户端JS文件,在前面安装服务端的步骤中,当npm安装完socket.io并搭建起WebServer后,这个JS文件就可以正常访问了。-->
    <!--<script src="http://localhost:3000/socket.io/socket.io.js"></script>-->
    <script src='../js/socket.io.js'></script>
    <script type="text/javascript" src="../js/jquery-1.11.3.js"></script>
    <!--<script type="text/javascript" src="./../js/client.js"></script>-->
</head>
<body>

<script>
    // 初始化页面登陆信息 name = prompt("请输入你的姓名:","");
    //获取当前时间 function show(){
        var mydate = new Date();
        var str = "" + mydate.getFullYear() + "-";
        str += (mydate.getMonth()+1) + "-";
        str += mydate.getDate() + " ";
        str += mydate.getHours() + ":";
        str += mydate.getMinutes() + ":";
        str += mydate.getSeconds();
        return str;
    }
    //WebSockets服务 var HTML5WebSockets = {}; HTML5WebSockets.socketio = { yoursocket: null,
        initialize: function () {


            //建立一个socket连接(页面地址http://192.168.1.16:3000)
//            HTML5WebSockets.socketio.yoursocket = io.connect('http://192.168.3.165:3000'); HTML5WebSockets.socketio.yoursocket =io('ws://192.168.3.165:3000', {transports: ['websocket']});

            //连接服务器 HTML5WebSockets.socketio.yoursocket.on('connect', function () { HTML5WebSockets.socketio.log('<p class="link">你好 '+name+' 你已成功连接服务器
'+show()+'</p>');
            });


            //[广播消息]接收到服务器的消息(此时服务器为广播消息YourMessageResponse name为服务端获取的名称) HTML5WebSockets.socketio.yoursocket.on('YourMessageResponse', function (data,name) { HTML5WebSockets.socketio.log('<span class="name"><span class="broadcastName">'+name+'</span><span class="broadcastMessage">'+data+'</span></span></br>'); $("#log").scrollTop(9999999);//消息置底 });
            //[广播消息]接收到服务器的消息(获取服务端登陆姓名) HTML5WebSockets.socketio.yoursocket.on('YourMessageResponse_1', function (name_1) { HTML5WebSockets.socketio.log('<p class="access">'+name_1+'加入了聊天
'+show()+'</p>'); $("#log").scrollTop(9999999);//消息置底 });

            //监听socket断开与重连 HTML5WebSockets.socketio.yoursocket.on('disconnect', function () { HTML5WebSockets.socketio.log('<p class="off">你与服务器断开连接</p>
');
            });

            //监听关闭客户端退出聊天(YouDisconnect) HTML5WebSockets.socketio.yoursocket.on('YouDisconnect',  function (data) { HTML5WebSockets.socketio.log('<p class="off">'+data+'退出了聊天</p>
');
            });

            //处理DOM元素 document.querySelector('#sendCustMes').onclick = function () { HTML5WebSockets.socketio.emitCustomMessageToServer(document.querySelector('#custMes').value); document.querySelector('#custMes').value = '';
            };
//            $(document).keydown(function (event) {
//                switch (event.keyCode) {
//                    case 13://回车处理DOM元素 //                    HTML5WebSockets.socketio.emitCustomMessageToServer(document.querySelector('#custMes').value);
//                    document.querySelector('#custMes').value = '';
//                    break;
//                }
//                return false;
//            });

            //获取初始登陆输入的name(因为获取初始化登陆name名称不需要点击之后进行) HTML5WebSockets.socketio.emitCustomMessageToServer_1(name);
        },

        //客户端发送消息到服务器(YourcustomMessage)客户端服务端 emitCustomMessageToServer: function (data) {
            //客户端自己发的消息 HTML5WebSockets.socketio.log( '<span class="name_1"><span class="myMessage">'+data+'</span><span class="myName">'+name+'</span></span>
'); HTML5WebSockets.socketio.yoursocket.emit('YourcustomMessage', data,name);
        }, log: function (message) { document.querySelector('#log').innerHTML += message;
        },
        //客户端发送消息到服务器(YourcustomMessage)客户端服务端(emitCustomMessageToServer_1是初始name用于显示 {‘**加入聊天’})
        //不需要点击进行发送到服务器 emitCustomMessageToServer_1: function (name_1) { HTML5WebSockets.socketio.yoursocket.emit('YourcustomMessage_1',name_1);
        }

    }
</script>

    <div id='log'></div>

    <div class="btn">
        <input type='text' id='custMes' />
        <button type='button' id='sendCustMes'>&#xe68c;</button>
    </div>
<script> HTML5WebSockets.socketio.initialize();
</script>

<script type="text/javascript" src="../js/index2.js"></script>
</body>
</html>



CSS:

body,html{ height:100%; margin: 0 auto;
}
#log{ overflow: auto; height: 85%;
}
.link{ font-size: 12px; text-align: center; border-bottom: 1px solid #EDECEA; padding-bottom: 5px; color: gray; box-shadow: 0px 3px 7px #FAFAFA;
}
.access{ font-size: 12px; text-align: center; border-bottom: 1px solid #EDECEA; padding-bottom: 5px; color: gray;
}
/*广播消息*/
.name{ display: inline-block; width: 98%; font-size: 14px; color: #3DBA98; line-height: 26px; margin-top: 10px; margin-left: 5px;

}
.broadcastMessage{ color: white; margin-left: 5px; margin-right: 13px; padding: 5px 10px 5px 10px; display: inline-block; border-radius: 5px; background-color: #3DBA98; box-shadow: 0px 1px 20px #DDDDDD; max-width: 90%;
}
/*我的消息*/
.name_1{ display: inline-block; text-align: right; font-size: 14px; color: #3DBA98; line-height: 26px; margin-top: 10px; margin-right: 5px; float: right; width: 100%; margin-bottom: 10px;
}
.myMessage{ color: black; margin-left: 10px; margin-right: 5px; padding: 5px 10px 5px 10px; display: inline-block; border-radius: 5px; background-color: white; box-shadow: 0px 1px 10px #DDDDDD; max-width: 89%;
}
.btn{ position: absolute; bottom: 10px; left: 0; margin-top: 10px; width: 100%; border-top:  1px solid #3DBA98; padding-top: 5px; background: white;
}
.btn input{ width: 80%; height: 30px; border: none; margin-left: 5px;
}
@font-face { font-family: iconfont; src: url(../font/iconfont.woff);
}
.btn button{ border:none; height: 50px; width: 50px; border-radius:50px; font-family: iconfont; font-size: 30px; text-align: center; color: white; background: #3DBA98;
}
.off{ font-size: 12px; text-align: center; padding-bottom: 5px; color: #3DBA98;
}



img及font就不上传了。




思考:由于时间关系没有做更多的功能,本来是想做发送图片视频,及存储聊天记录到数据库,登陆注册模块。群聊及私聊。看来还得加班加点。好吧。第一次发這么长的贴。就算勉励自己吧。

最新喜欢:

唯一的信仰唯一的信仰 doubleyongdouble...
游客


返回顶部

公众号

公众号