手机版

快速实现基于socket.io的实时通信应用

时间:2021-08-25 来源:互联网 编辑:宝哥软件园 浏览:

随着web技术的发展,使用场景和需求变得越来越复杂,客户端不再满足于简单地请求状态的需求。实时通信越来越多地应用于各个领域。

HTTP是客户端和服务器之间最常用的通信技术,但是HTTP通信只能由客户端发起,无法及时获取服务器的数据变化。您只能依靠定期轮询来获取最新状态。时效性无法保证,请求多了会增加服务器负担。

WebSocket技术应运而生。

WebSocket概念

与HTTP半双工协议不同,WebSocket是基于TCP连接的全双工协议,支持客户端和服务器之间的双向通信。

WebSocket使得客户端和服务器之间的数据交换更加容易,并且允许服务器主动将数据推送到客户端。在WebSocket API中,浏览器和服务器只需要完成一次握手,就可以直接创建持久连接,进行双向数据传输。

在WebSocket API中,浏览器和服务器只需要握手,然后浏览器和服务器之间就形成了一个快速通道。数据可以在它们之间直接传输。

实现

本地实现

WebSocket对象支持四种消息:打开时、消息时、丢失时和错误时。

连接建立

您可以通过javascript快速建立网络套接字连接:

var Socket=new WebSocket(url,[协议]);上面代码中的第一个参数url指定了连接的URL。第二个参数“协议”是可选的,它指定了可接受的子协议。

由于http协议以http://开头,所以WebSocket协议的URL以ws://开头,安全WebSocket协议以wss://开头。

当浏览器和网络套接字服务器之间的连接成功时,将触发一条未决消息。

socket . on open=function(evt){ };当连接失败、数据收发失败或数据处理错误时,浏览器会触发一条错误消息。

socket . one rror=function(evt){ };当浏览器收到WebSocketServer发送的连接关闭请求时,会触发onclose消息。

socket . onclose=function(evt){ };发送和接收消息

浏览器接收到WebSocketserver发送的数据时,会触发onmessage,参数evt包含server传输的数据。

socket . on message=function(evt){ };发送用于向服务器发送消息。

socket . send();窝

WebSocket是和HTML5一起提出来的,所以兼容性有问题。这时,——Socket.io中出现了一个非常好用的库

Socket.io封装了websocket,并包含其他连接模式。您可以使用socket.io在任何浏览器中建立异步连接。Socket.io包含服务器和客户端的库。如果浏览器使用socket.io的js,服务器也必须适用。

Socket.io是一个基于Websocket的客户机-服务器实时通信库。

socket.io的底层基于库引擎. io.Engine.io为socket.io提供了跨浏览器/跨设备双向通信的底层库。Engine.io通过Websocket和XHR封装了一个套接字协议。在较低版本的浏览器中,不支持Websocket,而是使用长轮询来实现兼容性。

API文档

Socket.io允许您触发或响应自定义事件。除了连接、消息和断开连接,您可以触发任何自定义事件名称。

连接建立

const socket=io(' ws ://0 . 0 . 0 . 0: port ');//port是自己定义的端口号让io=require(' socket . io ')(http);Io.on('连接',函数(套接字){})消息传递

首先,发送数据

Socket.emit(自定义发送字段,数据);第二,接收数据

Socket.on(自定义发送字段,函数(数据){console。日志(数据);})断开连接

首先,断开所有连接

让io=require(' socket . io ')(http);io . close();其次,客户端与服务器断开连接

//client socket.emit('close ',{ });//服务器socket.on ('close ',数据={ socket . disconnect(true));});房间和命名空间

有时候求转发到有如下的使用场景:1.服务端发送的消息有分类,不同的客户端需要接收的分类不同;2.服务端并不需要对所有的客户端都发送消息,只需要针对某个特定群体发送消息;

针对这种使用场景插座中非常实用的命名空间和房间就上场了。

先来一张图看看命名空间与房间之间的关系:

命名空间

服务端

of('/post ').on('connection ',function(socket){ socket。发出('新消息',{ mess: '这是邮政的命名空间` });});io.of('/get ').on('connection ',function(socket){ socket。发出('新消息',{ mess: '这是得到的命名空间` });});客户端

//索引。js const socket=io(' ws ://0。0 .0 .0: * * * */post’);socket.on('新消息',函数(数据){ console.log('index ',数据);}//消息。js const socket=io(' ws ://0。0 .0 .0: * * * */get’);socket.on('新消息',函数(数据){ console.log('message ',数据);}房间

客户端

//可用于客户端进入房间;socket.join('一号房间');//用于离开房间;离开(一号房间);服务端

io.sockets.on('connection ',function(socket){ //提交者会被排除在外(即不会收到消息)socket.broadcast.to('一号房间')。发出('新消息,数据);//向所有用户发送消息io.sockets.to(数据)。发出(“recive message”,“hello,房间中的用户');}用socket.io实现一个实时接收信息的例子

终于来到应用的阶段啦,服务端用node.js模拟了服务端接口。以下的例子都在本地服务器中实现。

服务端

先来看看服务端,先来开启一个服务,安装表达和socket.io

安装依赖

NPM安装-开发快速NPM安装-开发插座。超正析象管构建结节服务器

let app=require(' express ')();让http=require('http ').createServer(处理程序);让io=require(' socket。io’)(http);让fs=require(' fs ');http.listen(端口);//端口:输入需要的端口号函数处理程序{ fs。读取文件(_ dirname)索引。html ',函数(err,data){ if(err){ RES . write head(500);返回res.end('加载index.html时出错');} RES . write head(200);res.end(数据);});} io.on('连接',函数(套接字){ console.log('连接成功');//连接成功之后发送消息socket.emit('新消息,{ mess: '初始消息` });});客户端

核心代码——index.html(向服务端发送数据)

差异发送信息/div输入占位符='请输入要发送的信息/button onclick='postMessage()'发送/button //接收到服务端传来的名字匹配的消息socket.on('new message ',function(data){ console。日志(数据);});函数postMessage(){ socket。发出(' recive message ',{ message: content,time : new Date()});messlist。推送({ message :内容,time : new Date()});}核心代码——message.html(从服务端接收数据)

socket.on('new message ',function(data){ console。日志(数据);});效果

实时通讯效果

客户端全部断开连接

某客户端断开连接

命名空间应用

加入房间

离开房间

框架中的应用

NPM安装插座。io-client const socket=require(' socket。io-client()(“http://localhost :端口”);组件DidMount(){ socket。on(' log in ',(数据)={ console。日志(数据)});socket.on('add user ',(data)={ console。日志(数据)});socket.on('新消息',(数据)={ console。日志(数据)});}分析求转发到协议

头球

请求包

Accept-Encoding: gzip,deflate Accept-language : zh-CN,zh;q=0.9,en;q=0.8 Cache-Control:无缓存连接:升级cookie : mecia _ VISIT _ ID=1 icrle 1mzhdvi1 defntgnafjyg;token=0b 81 ffd 758 ea 4a 33 e 7724 d9 c 67 efbb 26;io=oui5v qe7 _ WnIHlKnAAAG host : 0 . 0 . 0 . 0:2699 origin : http://127 . 0 . 0 . 1:5500 pragma :无缓存Sec-WebSocket-extension s 3360 permessage-deflate;client _ max _ window _ bits Sec-web socket-key : pjso iplexrl0 uenpaofusia==Sec-web socket-version : 13 upgrade : web socket用户-agent : Mozilla/5.0(iPhone;Iphone OS 11 _ 0喜欢MAC OS x)apple WebKit/604 . 1 . 38(khtml,喜欢gecko)版本/11.0 mobile/15a372 safari/604.1请求包描述:

必须是有效的http请求格式;HTTP请求方式必须是GET,协议应不低于1.1,如GET/HTTP/1.1;必须包含升级标头字段,其值为“websocket”,以告知服务器此连接需要升级到web socket;必须包含“连接”标题字段,其值为“升级”;必须包含“Sec-WebSocket-Key”头字段,其值采用base64编码的随机16字节字符序列;如果请求来自浏览器客户端,还必须包括“来源”头字段。标头字段用于防止未经授权的跨域脚本攻击,服务器可以决定是否接受来自Origin的WebSocket连接。必须包含“Sec-webSocket-Version”头字段,为当前使用协议的版本号,当前值必须为13;可能包括“Sec-WebSocket-Protocol”,表示客户端支持的协议列表,服务器选择一个或者没有可接受的协议响应;可能包括“Sec-WebSocket-Extensions”,协议扩展,某一类型的协议可能支持多个扩展,通过这些扩展可以实现协议增强;可能包括任何其他域,如cookie。响应包

响应包描述:

connection : Upgrade Sec-web socket-accept 3360 i4 jyffwm 0 r1j 8 lrnd 3 yextabq=Sec-web socket-Extensions 3360 per Message-deflate Upgrade : web socket必须包含升级头字段,其值为“web socket”;必须包含连接头字段,其值为“升级”;必须包含Sec-WebSocket-Accept头字段,其值是将请求包的“Sec-WebSocket-Key”的值与字符串“258 eafa 5-e914-47da-95ca-c5ab 0dc 85 b 11”进行拼接,然后对拼接后的字符串进行sha-1运算,再进行base64编码,即“Sec”应答包中冒号后有空格;最后,需要两个空行作为响应包的结尾。请求数据

Eio : 3传输: WebSocket sid : 8uehk 2uumxohvjrzaaaeio :3指示engine.io协议版本3传输指示用于传输的sid : sessionid(字符串)帧的类型。

网络套接字协议使用帧来发送和接收数据,发送的帧数据可以在控制台-帧中查看。

帧数据前的数字是什么意思?

这是Engine.io协议,其中数字是数据包代码:

数据包类型id[数据]

0打开新传输时从服务器发送open——(重新检查)

1 close——请求关闭此传输而不关闭连接本身。

2客户端发送ping——。服务器应该用包含相同数据的pong数据包进行回复

客户端发送:2探测探测帧3 pong——由服务器发送,以响应ping数据包。

服务器发送:3响应客户端4 message——的实际消息,客户端和服务器应该使用数据来调用它们的回调。

5升级——在engine.io切换传输之前,它测试服务器和客户端是否可以通过此传输进行通信。如果测试成功,客户端会发送一个升级数据包,请求服务器刷新旧传输的缓存,并切换到新传输。

6个noop——noop包。主要用于接收传入的WebSocket连接时强制轮询周期。

例子

上面的截图是上面例子中数据传输的一个例子,大概过程分析如下:

如果连接握手成功,客户端将发送2个探测帧,服务器将发送一个响应帧3个探测帧。服务器将发送内容为5的升级帧。检查内容为6的探测帧后,客户端将发出轮询请求,并将传输通道传输到websocket连接。接下来,它开始定期ping/pong客户端和服务器(默认为25秒)以发送和接收数据。4代表engine.io的消息消息,后面是发送和接收的消息内容。为了知道客户端和服务器之间的链接是否正常,项目中使用的ClientSocket和ServerSocket都有一个心跳线程。该线程主要用于检测客户端和服务器是否正常链接,客户端和服务器是否正常链接主要通过乒乓过程来保证。

常规心跳发送间隔默认为socket.io设置的25m,上图也可以观察到。该时间间隔可以通过配置进行修改。

参见engine.io-protocol

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

版权声明:快速实现基于socket.io的实时通信应用是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。