大家好,很高兴又见面了,我是前端进阶,由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发! 什么是WebSocket?前言 WebSocket允许创建实时应用程序,这些应用程序比传统的API协议更快、开销也更小。WebSocket有时被称为高端计算机通信协议,通过WebSocket来建立客户端服务器通信通道。本文将深入探讨WebSocket的起源?WebSocket是什么?它是如何工作的?常见的建立WebSocket连接的6个通用的库。1。WebSocket出现之前的世界?1。1WebSockets之前:使用JavaScript编写Web脚本 1995年,NetscapeCommunications聘请了BrendanEich,目标是将脚本功能嵌入到其NetscapeNavigator浏览器中,JavaScript就这样诞生了。 微软也很快凭借InternetExplorer浏览器进入了赛场,这是最初的浏览器大战真正开始的地方。两家公司都在争夺谁能获取最好浏览器的宝座,因此不可避免地要定期向Netscape和InternetExplorer添加新特性和功能。 浏览器大战1。2WebSockets之前:XMLHttpRequest和AJAX的诞生 当时引入的两个最重要的功能是将Javaapplets嵌入页面的能力,以及Microsoft的ActiveX控件。 两者本质上是预编译的组件,可以选择在网页中呈现自己的嵌入式用户界面。 虽然通过Javaapplets提供了一些类似的网络功能,但最重要的后台通信功能首次出现在1999年,即MicrosoftXMLHTTPActiveXObject接口。它在InternetExplorer5。0中原生支持,无需安装插件,可以用一行JavaScript实例化,并且在处理Javaapplets时不会带来任何问题。 XMLHTTP对象可以静默地向服务器发出请求并接收响应,所有这些功能都无需重新加载页面或以其他方式中断用户操作。然后JavaScript代码可以处理响应并对页面进行修改,从而将大量丰富的体验集成到网站中。 常见的早期用例包括允许下拉框根据用户先前的输入填充选项,以及在填写用户注册表时即时验证用户名可用性。 比如下面用于实例化XMLHTTP对象的示例JavaScript代码:注意:ActiveXObject是老版本IE浏览器的私有属性,大多数浏览器并不支持constxmlhttpnewActiveXObject(Microsoft。XMLHTTP);xmlhttp。open(GET,apidemostration,true);xmlhttp。onreadystatechangefunction(){if(xmlhttp。readyState4){alert(xmlhttp。responseText);}};xmlhttp。send(null); XMLHTTP后来由于被其他浏览器采用而成为XMLHttpRequest事实上的标准。这大约是创造术语AJAX的时间,AJAX代表异步JavaScript和XML。下面是使用标准XMLHttpRequest对象的示例:constreqnewXMLHttpRequest();req。addEventListener(load,()console。log(this。responseText));req。open(GET,apidemostration);req。send(); 与以前代码结构基本类似,只是代码更加简洁。但是,无论如何,XMLHttpRequest仍然遵循用于检索原始HTML文档的相同HTTP请求响应模型。没有允许服务器主动连接用户或为更复杂的用例建立任何类型的通用双向连接的能力。 尽管如此,JavaScript一直在添加新的特性和功能,浏览器也在增强文档对象模型(DOM)。这导致在如何使用JavaScript来丰富用户与网页交互的体验方面具有越来越大的潜力。1。3孵化实时网络 当某件事在技术上可行,并且有较高的ROI时,通常会竭尽全力。因此,开发人员开始使用XMLHttpRequest来模拟浏览器和服务器之间的实时通信。 这些技术中最常见的是长轮询,打开与服务器的XMLHttpRequest连接并保持打开状态,直到不再需要通信后关闭! 下面是HTTP长轮询的大致流程: HTTP长轮询 在没有其他合适工具的情况下,对于Web应用程序开发人员来说,长轮询很难正确执行,并且充满了必须管理的意外复杂情况,其他Comet技术也是如此。2。WebSocket横空出世? WebSockets于2008年首次出现,并在2010年左右开始获得广泛的浏览器支持。 如上文所示,在WebSockets出现之前,实时网络已经存在,但它很难实现,速度较慢,并且是通过hack并非为实时应用程序设计的现有网络技术来实现的。网络是建立在HTTP协议的基础上,该协议最初被设计为一种请求响应机制。用户打开一个连接,描述想要的东西,得到一个响应,然后关闭连接。 Websocket建立流程 WebSocket是一种全双工协议,主要用于客户端服务器通信。它本质上是双向的,这意味着通信在客户端服务器之间来回发生。 使用WebSocket开发的连接会持续到任何g参与方停止连接为止。一旦一方断开连接,另一方将无法通信,因为连接会在前端自动断开。 WebSocket需要HTTP的支持来发起连接,当涉及到无缝数据流和各种不同步流量时,它是现代Web应用程序开发的支柱。3。WebSocket的场景覆盖? WebSocket是一种必不可少的客户端服务器通信工具,需要充分了解其作用和适用场景才能更好的使用它。在以下情况下可以使用WebSocket:开发实时网络应用程序 WebSocket最常见的用途是在实时应用程序开发中,它有助于在客户端持续显示数据。由于后端服务器不断发回此数据,WebSocket允许在已打开的连接中不间断地推送或传输此数据。WebSockets的使用使此类数据传输更快,并利用了应用程序的性能。创建聊天应用程序 聊天应用程序开发人员在一次性交换和发布广播消息等操作中调用WebSocket寻求帮助。由于使用相同的WebSocket连接来发送接收消息,因此通信变得简单快捷。游戏应用程序 在游戏应用程序开发过程中,服务器必须不间断地接收数据,而不需要刷新UI。WebSocket在不影响游戏应用程序UI的情况下实现了这一目标。4。WebsocketvsHTTP的异同? 由于HTTP和WebSocket都用于应用程序通信,因此人们常常感到困惑,很难从这两者中选择。如前所述,WebSocket是一种双向协议。与此相反,HTTP是一种单向协议,作用于TCP协议之上。 由于WebSocket协议能够支持不间断的数据传输,因此主要用于实时应用开发。HTTP是无状态的,用于开发RESTful和SOAP应用程序。SOAP仍然可以使用HTTP来实现,但是REST被广泛传播和使用。 Websocket和HTTP连接建立流程 在WebSocket中,通信发生在双端,这使其成为速度更快的协议。在HTTP中,连接只能在一端建立,这使得它比WebSocket更慢。 WebSocket使用统一的TCP连接,需要一方终止连接。在它发生之前,连接保持持续活动状态。HTTP需要为单独的请求建立不同的连接。请求完成后,连接会自动断开。5。WebSocket连接是如何建立的? 该过程从涉及使用新方案ws或wss的WebSocket握手开始。为了快速理解,您可以将它们分别视为HTTP和HTTPS。 注意:HTTP和WebSocket相交部分表示,WebSocket的握手阶段需要HTTP参与 使用此方案,服务器和客户端应遵循标准的WebSocket连接协议。WebSocket连接建立从HTTP请求升级开始,它具有几个标头,例如:Connection:Upgrade、Upgrade:WebSocket、SecWebSocketKey等。下面是这个连接是如何建立的大致流程。注意:WebSocket的握手阶段需要HTTP参与,连接建立后将会自动切换为WebSocket协议传输 4。1请求阶段 Connection:Upgrade:表示WebSocket握手,而SecWebSocketKey表示Base64编码的随机值,该值是在每次WebSocket握手期间随机生成的。除了上述之外,Key标头也是此请求的一部分。 上面列出的标头组合起来就形成了一个HTTPGET请求。它将包含类似的数据:GETws:websocketexample。com:8181HTTP1。1Host:localhost:8181Connection:Upgrade握手Pragma:nocacheCacheControl:nocacheUpgrade:websocket升级为websocket协议SecWebSocketVersion:13协议版本SecWebSocketKey:b6gjhT32u488lpuRwKaOWs随机生成 SecWebSocketVersion表示可供客户端使用的WebSocket协议版本。4。2响应阶段 响应标头SecWebSocketAccept具有在SecWebSocketKey请求标头中同等的作用。这与特定的协议规范有关,并被广泛用于防止误导信息。换句话说,它增强了API的安全性,并阻止配置不当的服务器在应用程序开发中造成失误。 在先前发送的请求成功后,将收到类似于下面提到的文本序列的响应:HTTP1。1101SwitchingProtocolsUpgrade:websocketConnection:Upgrade升级成功SecWebSocketAccept:rG8wsswmHTJ85lJgAE3M5RTmcCE 在客户端、服务端建立连接的安全性方面,可以通过下面一段话进行总结: WebSocket没有规定服务器可以在握手期间对客户端进行身份验证的任何特定方式。WebSocket服务器可以使用通用HTTP服务器可用的任何客户端身份验证机制,例如cookie、HTTP身份验证或TLS身份验证!5。几个可用的WebSocket库?5。1ws ws是一个简单易用、快速且经过全面测试的Node。jsWebSocket客户端和服务器。它绝对是一个标准实现,旨在完成协议的所有工作。但是,连接恢复、发布订阅等其他功能是您必须自己管理的问题。 以下是使用Node。js和WebSockets构建实时应用程序时需要实现的代码。客户端constWebSocketrequire(ws);导入constwsnewWebSocket(ws:www。host。compath);ws。on(open,functionopen(){ws。send(something);});监听ws。on(message,functionincoming(data){console。log(data);});服务端constWebSocketrequire(ws);导入获取Server模块constconswssnewWebSocket。Server({port:8080});启动WebSocket服务器wss。on(connection,functionconnection(ws){ws。on(message,functionincoming(message){console。log(received:s,message);});ws。send(something);});5。2WebSockets WS是ws的直接替代品,注重性能和稳定性。据我所知,WS是最快的WebSocket服务器实现,它由SocketCluster在后台使用。constWebSocketServerrequire(uws)。Server;获取Server模块constwssnewWebSocketServer({port:3000});functiononMessage(message){console。log(received:message);}监听connectionwss。on(connection,function(ws){ws。on(message,onMessage);ws。send(something);});5。3fayewebsocket fayewebsocket是客户端和服务器的标准WebSocket实现,作为Faye项目的一部分,起源于RubyonRails社区。 在下面的服务器示例代码中,可以看到处理连接升级和从入站套接字缓冲区转换消息帧的所有工作都由库提供的WebSocket类处理。与其他最小化解决方案一样,这是一个简洁的实现您需要自己处理特定于应用程序的问题。客户端代码constWebSocketrequire(fayewebsocket),导入获取Client模块constwsnewWebSocket。Client(ws:www。example。com);ws。on(open,function(event){console。log(open);ws。send(Hello,world!);});ws。on(message,function(event){console。log(message,event。data);});ws。on(close,function(event){console。log(close,event。code,event。reason);wsnull;});服务端代码constWebSocketrequire(fayewebsocket),consthttprequire(http);constserverhttp。createServer();导入获取Server模块server。on(upgrade,function(request,socket,body){if(WebSocket。isWebSocket(request)){varwsnewWebSocket(request,socket,body);ws。on(message,function(event){ws。send(event。data);});ws。on(close,function(event){console。log(close,event。code,event。reason);wsnull;});}});server。listen(8000);5。4Socket。io Socket。IO已经存在了一段时间,可以被认为是WebSockets的jQuery。它使用长轮询和WebSockets进行传输,默认情况下从长轮询开始,然后升级到WebSockets。 长轮询已经基本不需要,Socket。IO如今的主要吸引力是它的主动断连能力、自动支持JSON和命名空间,它们本质上是在同一客户端连接上多路复用的隔离消息通道。 Socket。IO实际上不能与通用的WebSockets解决方案互换,无论是在服务器端还是在客户端。它有自己的附加握手协议,每条消息中都包含一些附加元数据。客户端代码constiorequire(socket。ioclient);constsocketio();socket。emit(chatmessage,Hellothere);服务端代码constapprequire(express)();consthttprequire(http)。Server(app);启动server并传递给socket。io模块constiorequire(socket。io)(http);app。get(,function(req,res){res。sendFile(dirnameindex。html);});io。on(connection,function(socket){console。log(auserconnected);});http。listen(3000,function(){console。log(listeningon:3000);});5。5SocketCluster SocketCluster是一个功能齐全的客户端服务器消息传递框架,完全围绕WebSockets构建,并在底层使用WebSockets。 与Socket。IO等更简单的解决方案相比,SocketCluster需要稍微多一些安装,但通常很容易启动和运行。客户端代码constsocketsocketCluster。create();socket。emit(sampleClientEvent,{message:Thisisanobjectwithamessageproperty});服务端代码constSocketClusterrequire(socketcluster);关于实例化参数的具体含义可以阅读文档constsocketClusternewSocketCluster({workers:1,Numberofworkerprocessesbrokers:1,Numberofbrokerprocessesport:8000,TheportnumberonwhichyourservershouldlistenappName:myapp,AuniquenameforyourappSwitchwsEnginetoscuwsforaMAJORperformanceboost(beta)wsEngine:ws,AJSfilewhichyoucanusetoconfigureeachofyourworkersserversThisiswheremostofyourbackendcodeshouldgoworkerController:dirnameworker。js,JSfilewhichyoucanusetoconfigureeachofyourbrokersUsefulforscalinghorizontallyacrossmultiplemachines(optional)brokerController:dirnamebroker。js,Whetherornottoreboottheworkerincaseitcrashes(defaultstotrue)rebootWorkerOnCrash:true});5。6SocketCluster SockJS是一个浏览器JavaScript库,它提供了一个类似于WebSocket的对象。SockJS为您提供了一个连贯的、跨浏览器的JavascriptAPI,它在浏览器和Web服务器之间创建了一个低延迟、全双工、跨域的通信通道。客户端代码constsocknewSockJS(https:mydomain。commyprefix);sock。onopenfunction(){console。log(open);sock。send(test);};sock。onmessagefunction(e){console。log(message,e。data);sock。close();};sock。onclosefunction(){console。log(close);};服务端代码consthttprequire(http);constsockjsrequire(sockjs);constechosockjs。createServer({sockjsurl:http:cdn。jsdelivr。netsockjs1。0。1sockjs。min。js});创建Serverecho。on(connection,function(conn){conn。on(data,function(message){conn。write(message);});conn。on(close,function(){});});varserverhttp。createServer();echo。installHandlers(server,{prefix:echo});server。listen(9999,0。0。0。0); 参考资料 https:www。wallarm。comwhatasimpleexplanationofwhatawebsocketis https:ably。comtopicwebsockets https:github。comuNetworkinguWebSockets https:github。comsocketiosocket。io