当前位置: 首页 > Web前端 > HTML5

WebSocket初探

时间:2023-04-05 15:21:38 HTML5

WebSocket节点初探websocketsocket.io我们平时开发的网页,大部分都是主动“拉”的形式。如果需要更新页面内容,需要“刷新”一次,但是Slack工具可以主动接收信息,好像服务端可以主动向客户端推送信息,请研究一下这是如何实现的。WebSocketwebsocket是HTML5中新引入的协议。它是一个类似(HTTP、FTP在tcp/ip协议栈中属于应用层)的协议而不是一个简单的函数。它本身和一个基于TCP协议的新协议。WebSocketwebsocket的产生是基于web的实时性。说到这里,就不得不追溯一下网络的历史。在2005年之前(也就是ajax还没有诞生),如果我们想在一个页面上展示不同的内容,或者页面内的跳转,只能通过点击和路由来实现重定向。ajax诞生后,网页开始动态化。但是所有的HTTP通信仍然由客户端控制,这就需要长连接,周期性的轮询或者长轮询来与服务器进行通信来更新数据。WebSocket周期性轮询(ajax轮询)之前的服务器“推送”技术:浏览器在特定时间向服务器发送请求,以检查服务器是否有信息数据。优点:编写后端程序比较容易。缺点:大部分请求都是无用的,浪费带宽和服务器资源。示例:适用于小型应用程序。长轮询:其实和上面的原理类似,是对ajax轮询的改进和增强。客户端和服务端建立连接后,一直保持通信(阻塞模式)。如果服务器端没有新消息,他们就一直通信,直到服务器端有新消息,然后返回给客户端。客户端与服务器断开连接。这时客户端可以继续与服务器连接。优点:在没有消息的情况下不会频繁请求,资源消耗小。缺点:serverholdconnection会消耗资源,返回数据的顺序不保证,难于管理和维护。例子:老WebQQ、Hi网页版、FacebookIM。流量控制:通常在客户端页面使用隐藏窗口向服务器端发送长连接请求。服务端收到这个请求后做出响应,不断更新连接状态,保证客户端与服务端的连接不会过期。通过这种机制,服务器端的信息可以源源不断地推送给客户端。比如你在页面中嵌入了一个隐藏的iframe,将隐藏iframe的src属性设置为长连接请求或者xhr请求,那么服务端就会源源不断地向客户端输入数据。SSE,Comet,使用长链接进行通信。优点:消息即时到达,不发送无用的请求;管理也比较方便。缺点:服务器保持长连接会增加开销。示例:Gmail聊天FlashSocket:在页面中使用Socket类嵌入一个Flash程序。JavaScript通过调用Flash程序提供的Socket接口与服务器端的Socket接口进行通信。JavaScript在接收到服务器端发送的信息后控制页面。展示。优点:实现真正的即时通信,而不是伪即时。缺点:客户端必须安装Flash插件;非HTTP协议不能自动通过防火墙。示例:互联网互动游戏。在HTTP1.1和长链接以上的服务器“推送”技术中:长轮询和流量控制实际上是基于长链接实现的,也就是http1.1中所谓的keep-alive。多个HTTP请求和响应可以在一个TCP连接上传输,减少建立和关闭连接的消耗和延迟。HTTP是无状态的,也就是说,浏览器和服务器每进行一次HTTP操作,就建立一个连接,但任务结束时,连接就终止了。如果客户端浏览器访问的HTML或其他类型的网页包含其他网络资源,如JavaScript文件、图像文件、CSS文件等;浏览器遇到这样的web资源,会创建一个HTTP会话HTTP1.1和HTTP1.0相比,最大的区别是HTTP1.1默认支持持久连接(最新的http1.0可以显示指定的keep-活着),但它仍然是无状态的,或者说不可信。在向客户端发送请求的文件时,服务器不存储有关客户端的任何状态信息。即使客户端在几秒钟内再次请求同一个对象,服务器也不会回应说:我刚给它发送了这个对象。相反,服务器重新发送对象,因为它已经完全忘记了之前做了什么。由于HTTP服务器不维护客户端的状态信息,所以我们说HTTP是无状态协议(statelessprotocol)。基于http协议的长连接减少了请求,减少了建立连接的时间,但是每次交互都是由客户端发起的,客户端发送消息,服务端可以返回客户端消息。因为客户端不知道服务器什么时候准备好结果,所以客户端的很多请求都是多余的,只是维持一个心跳,浪费带宽。WebSocket简介WebSocketWebSocket协议诞生于2008年,2011年成为国际标准,所有浏览器都已经支持。WebSocket通信协议于2011年被IETF定义为标准RFC6455,并由RFC7936补充。许多人都知道关于HTML5的故事。w3c放弃了HTML,然后一群人(有人说这些人为公司工作,但官方文档说是个人)成立了WHATWG组织,推动HTML语言的延续。同时,他们也制定了很多关于Web的技术标准,这些标准也不断被权威部门采纳。WebSocket是WHATWG发布的部分WebApplication(即HTML5)的产物。它最大的特点是服务端可以主动向客户端推送信息,客户端也可以主动向服务端发送信息。是真正的双向平等对话,属于服务器推送技术的一种。基于TCP协议,服务器端实现相对容易。对HTTP协议有很好的兼容性。默认的端口也是80和443,而且握手阶段使用的是HTTP协议,所以在握手的时候不容易屏蔽,可以通过各种HTTP代理服务器。数据格式相对轻量级,性能开销小,通信高效。可以发送文本或二进制数据。没有同源限制,客户端可以与任何服务器通信。协议标识符是ws(如果加密则为wss),服务器地址是URL。其中Upgrade:websocketConnection:Upgrade告诉服务器我们发起了一个WebSocket请求。Sec-WebSocket-Key是一个Base64encode值,由浏览器随机生成,用于验证服务器是否真的是Websocket助手。那么,Sec_WebSocket-Protocol就是一个用户自定义的字符串,用来区分同一个URL下不同服务所需要的协议。最后,Sec-WebSocket-Version告诉服务器使用的WebsocketDraft(协议版本)。HTML5WebSocketAPI详细接口文档:MDNWebSocket创建对象:varws=newWebSocket(url,name);url为WebSocket服务器地址,name为发起握手的协议名称,可选。发送短信:ws.send(msg);msg是文本信息,其他类型可以二进制形式发送。接收消息:ws.onmessage=(function(){...})();错误处理:ws.onerror=(function(){...})();关闭连接:ws.close();我们使用这个测试接口wss://echo.websocket.org来做一个小demo。常见的html(下面的代码基本都是这样的结构):

简单的客户端例子

这里我们使用了KaazingWebSocket提供的接口,它会完整的返回我们发送的数据。

状态:

返回数据:

发送关闭JS:varshow=document.getElementById('state'),msg=document.getElementById('msg'),st=document.getElementById('sendText'),sb=document.getElementById('sendBtn');if("WebSocket"inwindow){varws=newWebSocket('wss://echo.websocket.org');ws.onopen=function(e){show.innerText='WebSocket连接成功~';ws.send('你好WebSockets!');};ws。onmessage=function(e){msg.innerText=e.data;};ws.onclose=function(e){show.innerText='WebSocket连接关闭~';}sb.addEventListener('click',function(){ws.send(st.value);})}else{alert('你的浏览器不支持WebSocket');}nodejs-websocketnodejs-websocket是一个nodeJs模块,我们可以用它来方便的为我们之前的代码单独搭建一个WebSocketnodeJs服务Sideyarnaddnodejs-websocketvarws=require("nodejs-websocket")//尖叫服务器示例:"hi"->"HI!!!"varserver=ws.createServer(function(conn){console.log("新连接")conn.on("text",function(str){console.log("Received"+str)conn.sendText(str.toUpperCase()+"!!!")})conn.on("close",function(code,reason){console.log("Connectionclosed")})}).listen(8001)Socket.io一些某种程度上,socket.io就是websocket,但是socket.io和websocket不是一回事,而websocket可以说是socket.io的一个子集,socket.io的实现方式其实有五种,websocket只是其中一种其中,但默认情况下,我们建立的socket.io连接,底层也是调用websocket的实例。当我们io.connect()建立套接字连接时,返回命名空间实例。命名空间实例中有一个套接字实例。在新建连接或者发送消息的时候,namespace->socket->transport->websocket(xhrpolling...),其实真正发送消息的发送者还是底层的websocket或者xhrpolling或者其他类型,而socket.io只是一个组织者。当我们需要建立连接的时候,就会在它内部选择一种连接方式,然后实现连接。Socket.io在Polling中实现了那些通信机制?Adobe?Flash?SocketAJAXlongpollingAJAXmultipartstreamingForeverIframeJSONPPollingWebSocket和HTTP以及Socket应用层协议,WebSocket在现代软件开发中被越来越多的实践,和HTTP有一些相似之处,也有人会把WebSocket和Socket套接字混淆,所以它们之间有什么相同点和不同点?对于WebSocket和HTTP,我们先看一下这两个协议的截图来理解。相同点是基于TCP的应用层协议。两者都使用请求/响应模型来建立连接。连接建立时的错误处理方式相同,WS在此阶段可能会返回与HTTP相同的返回码。可以在网络中传输数据。不同的是WS使用HTTP建立连接,而是定义了一系列HTTP中没有用到的新头域。WS连接不能通过中间人转发,必须是直连。WS连接建立后,通信双方可以随时向对方发送数据。WS连接建立后,数据传输使用帧来传递,不再需要Request报文。WS的数据框是有序的。WebSocket和Socket其实就像Java和JavaScript一样,WebSocket和Socket没有太大关系。Socket可以有多种含义,与IT相关的本意大致是指端到端的连接,两端称为Socket。对于IT从业者来说,通常指的是TCP/IP网络环境中的两个连接端。大多数API提供者(如操作系统,JDK)往往会提供基于这个概念的接口,所以对于开发读者来说,往往是在谈论一个编程概念。同时,操作系统中的进程间通信也有Socket的概念,只是这个Socket并不是基于网络传输层的协议。套接字实际上不是协议。它工作在OSI模型的会话层(第5层),是一个抽象层,其存在是为了方便直接使用低层协议(通常是TCP或UDP)。Socket是应用层与TCP/IP协议族之间进行通信的中间软件抽象层,是一组接口。在设计模式上,Socket实际上是一种门面模式,将复杂的TCP/IP协议族隐藏在Socket接口的背后。对于用户来说,一套简单的接口就是全部,Socket组织数据以满足指定的协议。为了使主机A的应用程序能够与主机B的应用程序通信,必须通过Socket建立连接,而Socket连接的建立必须要求底层的TCP/IP协议建立TCP连接.建立TCP连接需要底层IP协议来寻址网络上的主机。我们知道网络层使用的IP协议可以帮助我们根据IP地址找到目标主机,但是一台主机上可能运行着多个应用程序,如何与指定的应用程序通信必须通过TCP或UPD,即要指定的端口号。这样,一个Socket实例就可以唯一代表一个应用程序在主机上的通信链路。WebSocket则不同,它是一个完整的应用层协议,包括一套标准的API。因此,在使用上,WebSocket更易用,而Socket更灵活。浏览器支持websocketapi在浏览器端的广泛实现似乎只是时间问题。值得注意的是,服务端没有标准的api,每个实现都有自己的一套api,tcp也没有类似的提案,所以使用websocket开发服务端存在一定的风险。您可能会被锁定在某个平台或将来被迫升级。本文相关的demo已经放在作者的Github上:小楼兰的github