WebSocket
websocket
可以实现客户端与服务端数据的实时通信。(长连接)
网络通信过程中的长连接与短连接
HTTP
协议是一款基于短连接模式的协议。意味着需要通信时,客户端向服务端发送连接请求,一旦连接建立,开始通信,接收响应,响应接收完毕后连接将断开。
短连接模式可以极大的节省服务端资源(CPU、内存、连接数)。
websocket
属于长连接,意味着需要通信时,客户端向服务端发送websocket
连接请求,一旦连接建立成功,两端通信的过程中连接不断开。这个过程中,双方都可以自发的向对方发消息,对方可以实时接收这些消息。
例如:即时通讯、游戏等。
长连接模式可以实现实时通信,但是会长时间占用服务端资源。在做技术选型时可以尝试使用短连接的http协议发送心跳包,模拟长连接的功能。
什么是websocket
?
websocket
是一种在单个TCP
连接上进行**全双工通信(通信过程中允许两个方向同时进行数据传输)**的一种通信协议。是一款长连接协议。它具备数据包格式小,通信高效、既可以发送文本,又可以发送二进制的特点。
如何使用代码建立websocket
连接并实现实时通信?
socket.io
socket.io
是一个为浏览器与服务器之间提供实时的、双向的、基于事件通信的网络通信库。实现了webosocket
协议,提供了相关API
,抹平了一些技术细节及兼容性。
导入socket.io.js
io('ws://ip:port/') //建立websocket连接
require('socket.io')
serversocket.on('connection', (client)=>{
连接成功
})
建立websocket
连接
客户端
html
引入socket.io.js
<script src="socket.io.js"></script>
调用
socket.io
提供的方法,试图建立连接:<script> // socket:套接字 // 封装了与服务端进行交互的属性和方法 let socket = io('ws://localhost:3000/'); </script>
服务端
websocket
服务是挂载在web
服务基础之上的。也就是说weboscket
是内嵌在一个express
服务内部的。express
将启用3000
端口提供普通的web
服务。具体步骤如下:
新建一个
nodejs
项目,安装express
、socket.io
等模块。# 必须进入serversocket项目目录下,执行安装命令: npm init npm install --save express npm install --save socket.io
新建
index.js
,引入express
、socket.io
。基于
socket.io
接收客户端的websocket
连接。// socketserver/index.js const express = require('express'); const app = express(); // 获取express底层的http服务 const http = require('http').createServer(app); // 加载socket.io模块时 把路由挂载到底层的的http服务之上 const serversocket = require('socket.io')(http); // 设置public目录为静态资源托管目录 app.use(express.static('public')); // 监听客户端的websocket连接,一旦有客户端连接,就会触发 // ‘connection’事件,编写事件处理函数处理该事件即可。 // 在事件处理函数中将自动传入与客户端交互所需要的socket对象 serversocket.on('connection', (socket)=>{ console.log('有客户端进来了:'+socket.id); }) http.listen(3000, ()=>{ console.log('server is running...'); })
客户端与服务端之间进行通信
客户端向服务端发消息
客户端发送:
let socket = io('ws://localhost:3000/');
// socket.emit(key, value);
socket.emit('textmsg', '你瞅啥?');
服务端接收:
serversocket.on('connection', (socket)=>{
console.log('有客户端进来了:'+socket.id);
// 通过socket对象接收客户端发来的消息
// socket.on(key, callback)
socket.on('textmsg', function(res){
console.log(res);
})
})
服务端向客户端发消息
服务端:
socket.on('textmsg', function(res){
console.log(res);
// 给当前socket客户端回复消息
socket.emit('textmsg', '丑你咋地!');
})
客户端:
let socket = io('ws://localhost:3000/');
socket.on('textmsg', (res)=>{
console.log(res);
})
服务端向所有客户端广播消息
服务端:
serversocket.on('connection', (socket)=>{
console.log('有客户端进来了:'+socket.id);
serversocket.emit('textmsg', '内容'); // 给所有客户端都发消息
})
实现群聊天室
需求如下:
-
在聊天界面中建立
websocket
连接。 -
一个客户端在消息发送区发送消息,服务端接收消息后把该消息分发给所有客户端。
-
客户端接收服务端发回来的消息,打印。
-
接收到的消息,上屏。
-
更新当前在线人数。
- 在服务端存储一个全局的变量
count
。用于保存当前在线人数,默认值:0。 - 一旦有客户端连接进来,
count++
。 - 一旦有连接断开,
count--
。 - 一旦服务端
count
有变化,就向所有客户端发个消息,告诉它们最新的count
的值,客户端接收到最新的count
后更新界面。
- 在服务端存储一个全局的变量
-
实现登录业务。在
index.html
填写昵称后点击登录,跳转到chart.html
。把用户昵称和头像文件名都传递过来。window.location="chart.html?name=东东&avatar=1.jpg"
-
在发消息时,带着用户信息一起发送消息:
emit('textmsg', { name:'zs', avatar:'1.jpg', content:'xxxx' } )
私聊
实现思路:
-
客户端发消息时,除了
content
、name
、avatar
之外还需要发送to
(对方的昵称){ name: '亮亮', avatar: '16.jpg', content: '你最近还好吗?我好想你', to: '东东' }
-
服务端接收消息后,判断到底给谁发,需要找到与对方交互时所必须的
socket
对象(前提是所有用户连接成功后,把这些socket
对象都得存起来)。调用该socket
对象的emit
即可完成私聊。
-