实现一个简单的WebSocket聊天室
Websocket简介
WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
在 WebSocket API 中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
为什么传统的HTTP协议不能做到WebSocket实现的功能?这是因为HTTP协议是一个请求-响应协议,请求必须先由浏览器发给服务器,服务器才能响应这个请求,再把数据发送给浏览器。换句话说,浏览器不主动请求,服务器是没法主动发数据给浏览器的。
使用Socket.io
Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5
socket.io特点
- 实时分析:将数据推送到客户端,这些客户端会被表示为实时计数器,图表或日志客户。
- 实时通信和聊天:只需几行代码便可写成一个Socket.IO的”Hello,World”聊天应用。
- 二进制流传输:从1.0版本开始,Socket.IO支持任何形式的二进制文件传输,例如:图片,视频,音频等。
- 文档合并:允许多个用户同时编辑一个文档,并且能够看到每个用户做出的修改。
具体事件和方法参见:https://www.w3cschool.cn/socket/
后端代码
使用node.js + express快速搭建一个服务器,引入Socket.io ,代码如下:
var app = require("express")(); var http = require('http').Server(app); //引入socket.io var io = require('socket.io')(http); //加载前端页面 app.get('/',function(req,res){ res.sendFile(__dirname + '/index.html'); }); //连接socket var userName = ''; io.on('connection',function(socket){ console.log('a user connected:'+socket.id); userName = socket.id.substr(0,10); socket.broadcast.emit('chat message','欢迎用户: ' + userName + '加入房间'); socket.on('disconnect',function(){ console.log('user disconneted'); }); socket.on('chat message',function(data){ io.emit('chat message',data); console.log('message : ' + data.msg); }); }); http.listen(3000,function(){ console.log('listening on *:3000'); });
前端代码
<!doctype html> <html> <head> <title>Socket.IO chat</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font: 13px Helvetica, Arial; } form { padding: 3px; position: fixed; bottom: 0; width: 100%; border-top: 1px solid gray; } form input { border: 0; padding: 10px; width: 85%; margin-right: .5%; } form button { width: 14%; background: rgb(130, 224, 255); border: none; padding: 10px; } #messages { list-style-type: none; margin: 0; padding: 0; } #messages li { padding: 5px 10px; height: 40px; line-height: 30px; } #messages li:nth-child(odd) { background: #eee; } .all_msg{ text-align:center; } .my_msg{ text-align:right; } .websocket { width: 400px; height: 800px; position: absolute; top: 5%; left: 50%; transform: translateX(-50%); background: #f7f7f7; border: 1px solid gray; } </style> </head> <body> <div class="websocket"> <ul id="messages"></ul> <form action=""> <input id="m" autocomplete="off" /><button>Send</button> </form> </div> </body> <script src="/socket.io/socket.io.js"></script> <script src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js"></script> <script> var socket = io(); var userName = ''; socket.on('connect', () => { userName = socket.id.substr(0, 10); console.log(userName) }); $('form').submit(function () { var msg = $('#m').val(); socket.emit('chat message', { msg, userName }); $('#m').val(''); return false; }); socket.on('chat message', function (data) { if (typeof data == 'string') { $('#messages').append(`<li class="all_msg">${data}</li>`);//广播 } else { if (userName == data.userName) { $('#messages').append(`<li class="my_msg"><span>${data.msg}</span>:<span>我</span></li>`); } else { $('#messages').append(`<li><span>${data.userName}</span>:<span>${data.msg}</span></li>`); } } }); </script> </html>
效果展示
浏览器上打开多个窗口,便可进行对话