宝哥软件园

网络套接字简介及应用

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

定时刷新的缺点及改进

在web开发中,可能会有这样一种场景,一些内容写在网页的某个区域,但是这些内容并不是固定的,即使观看网页的人什么都不做,也会随着时间的推移而改变。股票报价、活动或游戏列表就是一个常见的例子。

在这方面,通常的做法是使用setTimeout()或setInverval()定期执行任务。任务内容是Ajax访问服务器一次,成功获取返回数据后更新页面。

这种定期刷新会有一些不足之处:

频繁的定时网络请求对浏览器(客户端)和服务器来说都是一种负担,尤其是当网页中有多个定时刷新区域时。一定数量的计划任务可能是不必要的,因为服务器可能没有新数据,或者它可能返回与上一个相同的内容。页面内容可能不是最新的,因为服务器可能刚刚更新了数据,但下一个计划任务尚未开始。综上所述,造成这些缺点的主要原因是服务器的响应总是被动的。HTTP协议限制通信总是从客户端请求,然后服务器返回响应。

因此,如果服务器能够主动向客户端发送信息,这些缺点就可以得到很大的改善。WebSocket是实现这种双向通信的新协议。

WebSocket是一种基于HTTP的功能添加协议

WebSocket最初是由html5提出的,但现在已经发展成为一个独立的协议标准。WebSocket可以分为协议和API两部分,分别由IETF和W3C制定。

我们先来看看建立WebSocket协议的过程。

要实现WebSocket通信,客户端首先需要发起一个普通的HTTP请求(即WebSocket的建立依赖于HTTP)。请求消息可能如下所示:

GET ws ://web socket . example.com/HTTP/1.1 host : web socket . example.com Upgrade: websocket connection : Upgrade origin : http://example.comsec-web socket-key : palokxsgshttpihrjdwlvzq==Sec-web socket-version :13,其中HTTP头字段Upgrade : web socket和Connection:确认上述请求后,支持网络套接字的服务器应该返回一个响应,状态代码为101交换协议:

HTTP/1.1 101交换协议升级: websocket连接3360升级Sec-WebSocket-Accept : nru 4 kapupjjwyrnzdveqoxvlm=其中字段Sec-websocket-Accept为服务器确认并加密前一个客户端发送的Sec-WebSocket-Key后的结果相当于一个验证,从而帮助客户端确定对方是真实可用的web socket服务器。

经过验证,这个握手响应建立了WebSocket连接,然后服务器可以主动向客户端发送信息。此时的状态更像是服务器和客户端在通话。谁想告诉对方什么信息,尽管问。

一旦建立了WebSocket连接,HTTP就不再用于后续的通信,而是使用WebSocket独立的数据帧(这个帧在某种程度上是可以看到的,后面会讲到)。

整个过程是这样的:

简单应用示例

应用网络套接字时有几件事要做:

选择支持WebSocket的浏览器。添加在网页中创建网络套接字的代码。添加使用WebSocket在服务器端进行通信的代码。计算机网络服务器

以Node的服务器为例,我们使用ws作为组件来构建一个支持WebSocket的服务器:

var request=require(' request ');var dateFormat=require(' dateFormat ');var WebSocket=require('ws '),WebSocketServer=WebSocket。Server,WSS=new WebSocketserver({ port : 8080,path : '/guest ' });//收到客户端的连接请求后,开始推送消息wss.on ('connection ',function (ws) {ws.on ('message ',function(message){ console . log(' received 3360% s ',message);});sendGuestInfo(ws);});函数SendGuestinFo(ws){ request(' http://uinames.com/API?region=china ',function(错误,响应,body) { if(!错误响应. status code===200){ var JSON object=JSON . parse(body),guest=JSON object . name JSON object .姓氏,guestInfo={ guest: guest,time: dateFormat(new Date(),' hh :mm 3360s ')};send if(ws . readystate===WebSocket . open){///,send ws . send(JSON . string fy(guest info));//使用random来“安装”更像是推一些settimeout(function(){ send guestinfo(ws);},(math . random()* 5 ^ 3)* 1000);} } });}此示例使用名称生成站点uinames的API服务来生成数据,如{guest:' person name ',time: ' 153360263:01 ' }。函数sendGuestInfo()会不时执行,并通过send()方法将包括名称和时间在内的信息发送给客户端。此外,请注意,send()方法需要以字符串形式发送json数据。

这就像服务器自己在做一些事情,然后在必要的时候通知客户端一些信息。

客户

在客户端,我们使用本机javascript(仅支持WebSocket浏览器):

var socket=new WebSocket(' ws ://localhost :8080/guest ');socket . onopen=function(OpenEVENT){ console . log(' WebSocket contec ted . '));};socket . on message=function(messageEvent){ var data=messageEvent . data,dataObject=JSON . parse(data);console . log(' Guest at ' DataObject . time ' : ' DataObject . Guest);};socket . onerror=function(error event){ console . log(' WebSocket error : ',error event);};socket . onclose=function(closeEvent){ console . log(' WebSocket closed ')。);};WebSocket的URL格式为ws://和ws ://。所以需要注意URL地址的书写,这也包括注意WebSocket服务器的路径(比如这里的/guest)。这是localhost,因为它是一个本地示例。

客户端代码的流程很简单:创建WebSocket对象,然后指定onopen和onmessage等事件的回调。其中,onmessage是客户端和服务器端通过WebSocket进行通信的关键事件。如果你想在收到服务器通知后做点什么,只需要把它写在onmessage事件的回调函数中。

效果和分析

通过node server启动WebSocket服务器后(假设服务器端的文件名是server.js),打开一个前面有客户端代码的html(直接文件路径file 3360///就可以了),可以得到这样的结果:

通过联系前面的客户端代码,我们可以认为实际上从创建WebSocket对象的语句开始,就会发送连接请求,很快就会建立WebSocket连接(如果没有错误的话),然后就可以收到服务器的通知了。如果此时客户端仍然想告诉服务器一些事情,请执行以下操作:

socket.send('你好,服务器!');服务器可以接收:

当然,这也是因为消息事件的回调也是在服务器端的代码中设置的。在这个客户机和服务器都是javascript的例子中,服务器和客户机都使用send()发送信息,并通过消息事件设置回调,可以说在形式上非常一致。

其他可用数据类型

WebSocket send()可以发送两种消息,除了之前使用的字符串类型之外,还有Blob和ArrayBuffer。

它们都代表二进制数据,可用于发送原始文件数据。例如,这是一个发送Blob类型数据以将图片上传到服务器的示例:

var fileEl=document . getelementbyid(' image _ upload ');var file=FileEl . files[0];socket.send(文件);然后服务器可以像这样保存文件:

var fs=require(' fs ');wss.on('connection ',function(ws) { ws.on('message ',function(message){ fs . write file(' upload . png ',message,' binary ',function(error) { if(!错误){控制台.日志('文件已保存');} });});});当客户端接收到二进制数据时,需要注意的是,WebSocket对象有一个binaryType属性,初始值为“blob”。因此,如果接收到的二进制数据是ArrayBuffer,这应该在接收之前完成:

socket . Binarytype=' array buffer ';其他网络套接字服务器

其他语言比如WebSocket服务器呢?下面是一个php网络套接字服务器(使用棘轮)的例子:

?phpuse棘轮 ConnectionInterface使用棘轮消息组件接口;需要__DIR__。/vendor/autoload . PHP ';类GuestServer实现messagecomponent interface { public function on open(ConnectionInterface $ conn){ $ conn-send('服务器现在正在监听您。'));} public function on message(ConnectionInterface $ conn,$ msg){ $ conn-send($ this-generateGuestInfo());}公共函数onClose(ConnectionInterface $ conn){ }公共函数onError(ConnectionInterface $ conn, Exception $ e){ $ conn-close();}私有函数generateGuestInfo(){ $ jsonString=file _ get _ contents(' http://uinames.com/API?region=China’);$ JSON object=JSON _ decode($ JSON string,true);$guest=$jsonObject['name']。$jsonObject['姓氏'];$guestInfo=数组(' guest'=$guest,' time'=date('H:i:s ',time()),);返回JSON _ encode($ guestInfo);}}$app=new棘轮App('localhost ',8080);$ app-route(“/guest”,new GuestServer(),array(“*”);$ app-run();在本例中,服务器还返回了{guest:' person name ',time:' 15336026:01'}的json数据。但是,与Node不同的是,php可以很容易地用setTimeout()实现异步计时任务,所以在这里,在客户端发送任何信息一次后,它会转到uinames获取信息并返回。

也可以看出,php搭建的WebSocket服务器还是类似的,其功能主要是通过open、message等WebSocket事件来实现的。

在Chrome开发工具中查看网络套接字数据框

在Chrome开发工具中选择Network,然后找到WebSocket的请求,在这里可以选择Frames。请参见框架中的网络套接字数据框架:

你可以看到它和聊天记录非常相似,其中标有浅绿色的部分是客户端发送给服务器的。

结论

一般来说,将服务器和客户端拉进聊天窗口是一个很好的主意。

甚至在形式上,WebSocket的事件回调感觉比常规任务更亲密。

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

更多资讯
游戏推荐
更多+