当前位置:网站首页>Caché WebSocket
Caché WebSocket
2022-07-04 17:09:00 【用户7741497】
使用WebSockets (RFC 6455)
web
是围绕请求/响应范例构建的:客户机向服务器发送请求,服务器通过向客户机发送响应进行响应。此范式和HTTP
本身不允许此通信协议的反向形式,即服务器与客户机启动请求/响应周期。已经开发了许多技术来解决了这个问题,即服务器可以启动与客户机的对话。这些技术通常被称为基于推送或 comet-based
的技术,它们都存在不适合在web基础设施上进行全面部署的问题。目前使用的三种主要技术如下所述。
Short Polling 短轮询
使用这种技术,客户端定期发送HTTP请求来检测服务器状态的变化,服务器被编程为立即响应。空响应表示没有变化。
问题:
- 轮询频率(和响应能力)受到客户机可以容忍的刷新延迟的限制。
- 每个请求都是一个完整的
HTTP
请求/响应往返过程,这会导致大量的HTTP
流量,而这又会给服务器和网络基础设施带来无法接受的负担 - 每个消息交换都承载着
HTTP
协议的开销,如果消息大小超过了最大传输单元(MTU
)(通常是以太网的1500字节),则会特别繁重。
Long Polling 长轮询
使用这种技术,客户端发送HTTP
请求,但服务器只在需要通知客户端更改时才响应。客户端通常在服务器发送响应消息时发送另一个“长轮询”请求。
问题:
- 每个请求都是完整的
HTTP
请求/响应往返,尽管这种技术涉及的HTTP
通信量比短轮询少。 - 还有维护持久连接的负担。
- 每个消息交换都带有
HTTP
协议的开销。 - 超时可能会对该技术的成功产生不利影响。
HTTP Streaming HTTP流
这种技术利用了HTTP协议在客户端和服务器之间保持持久(或“KeepAlive”
)连接的能力。客户端发送一个HTTP请求,该请求永久保持打开状态,只有在需要通知客户端更改时,服务器才会响应。服务器在发送响应消息后不终止连接,客户机等待来自服务器的下一条消息(或向服务器发送自己的消息)。
问题:
- 整个客户机/服务器交换是在一个
HTTP
请求/响应往返过程中构建的,并不是所有服务器都支持这种方式。 - 这种技术的成功可能会受到代理和网关等中介行为的不利影响。(曾经手机上设置代理IP就不能正常访问请求)
- 任何一方都没有义务立即向另一方提交部分回复。
- 客户端缓冲方案可能会对该技术产生不利影响。
- 超时可能会对该技术产生负面影响。
WebSockets协议
WebSockets
协议(RFC 6455
)通过在客户端和服务器之间提供一个全双工的面向消息的通信通道,解决了允许服务器主动将消息推送到客户端的基本需求。该协议被设计为在客户端和服务器之间已经建立的标准TCP
通道上操作,因此是安全的。换句话说,已经使用的通道支持web浏览器和web服务器之间的HTTP
协议。
WebSockets
协议及其API由W3C
标准化,客户端部分包含在HTML 5
中。
中介体(如代理和防火墙)应该设置成知道(并支持)WebSockets
协议。
浏览器支持
在为WebSockets
协议创建最终标准的过程中,已经进行了几次迭代,每一次都有不同程度的浏览器支持。历史概述如下。
- Hixie-75:
- Chrome 4.0+5.0, Safari 5.0.0
- HyBi-00/Hixie-76:
- Chrome 6.0-13.0, Safari 5.0.2+5.1, Firefox 4.0 (disabled), Opera 11 (disabled)
- HyBi-07+:
- Chrome 14.0, Firefox 6.0, IE 9 (via Silverlight extension)
- HyBi-10:
- Chrome 14.0+15.0, Firefox 7.0+8.0+9.0+10.0, IE 10 (via Windows 8 developer preview)
- HyBi-17/RFC 6455
- Chrome 16
- Safari 6
- Firefox 11
- Opera 12.10/Opera Mobile 12.1
- IE 10 最后突出显示的部分对于开发可移植web应用程序是最重要的。
服务器的支持
可以说,面向服务器的基于javascript
的Node.js
技术提供了最复杂、目前最成熟的WebSockets
协议实现。WebSockets
一直与Node.js
紧密联系在一起。但是,其他web服务器技术正在迅速赶上来,所有主要web服务器的最新版本现在都提供了WebSockets
支持,如下所示。
- Node.js
- 全版本
- Apache v2.2
- IIS v8.0
- Windows 8 and Windows Server 2012
- Nginx v1.3
- Lighttpd 高亮显示的部分对于使用CSP开发可移植web应用程序来说是最重要的。
协议的细节
创建WebSocket
涉及到客户端和服务器之间的有序消息交换。首先,必须进行WebSocket
握手。握手基于并类似于HTTP
消息交换,因此它可以毫无问题地通过现有的HTTP
基础设施传递。
- 客户端发送
WebSocket
连接的握手请求。 - 服务器发送握手响应(如果可以的话)。
web服务器识别握手请求消息中的传统HTTP
头结构,并向客户机发送类似构造的响应消息,表明它支持WebSocket
协议。如果双方都同意,那么通道将从HTTP
(http://)
切换到WebSockets
协议(ws://)
。
当协议成功切换后,通道允许客户端和服务器之间的全双工通信。
单个消息的数据帧很少。
典型的来自客户端的WebSocket
握手消息
GET /csp/user/MyApp.MyWebSocketServer.cls HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat
Sec-WebSocket-Version: 13
Origin: http://localhost
典型的WebSocket
握手消息来自服务器
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
请注意客户端握手消息如何请求将协议从HTTP
升级到WebSocket
。还要注意客户机(secwebsocket - key
)和服务器(secwebsocket - accept
)之间唯一密钥的交换。
WebSockets客户端代码(JavaScript)
在浏览器环境中,WebSocket
协议的客户端是用JavaScript
代码实现的。标准教科书详细描述了使用模型。本文件将简要介绍基本知识。
创建WebSocket
- 第一个参数表示标识
WebSocket
应用程序服务器端的URL
。 - 第二个参数是可选的,如果有,指定服务器必须支持的子协议,以便
WebSocket
连接成功。
var ws = new WebSocket(url, [protocol]);
例子:
ws = new WebSocket(((window.location.protocol == "https:")
? "wss:" : "ws:") \
+ "//" + window.location.host
+ /csp/user/MyApp.MyWebSocketServer.cls);
$("#conUrl").val((window.location.protocol == "https:" ? "wss:" : "ws:") + "//" + window.location.host + "/dthealth/web/PHA.COM.WebSocket.cls" )
请注意,如何将协议定义为ws
或wss
,这取决于是否使用SSL/TLS
保护底层传输。
只读属性ws.readyState
定义连接的状态。它可以取以下值之一:
- 0 连接尚未建立。
- 1 连接已经建立,通信是可能的。
- 2 连接以结束握手为准。
- 3 连接已关闭或无法打开。
只读属性ws.bufferedAmount
定义UTF-8文本的字节数,使用send()
方法排队。
WebSocket事件
以下事件是可用的。
ws.onopen
在建立套接字连接时打触发。ws.onmessage
当客户机从服务器接收数据时触发。
在event.data
中接收的数据。
ws.onerror
当通信中发生错误时触发。ws.onclose
当连接关闭时触发。
WebSocket方法
以下是可用的方法。
ws.send(data)
将数据传输到客户端。ws.close()
关闭连接。
WebSockets服务器代码(CSP)
实现WebSocket
服务器的基本Caché 类是%CSP.WebSocket
。
当客户机请求一个WebSocket
连接时,初始HTTP
请求(初始握手消息)指示CSP
引擎初始化应用程序的WebSocket
服务器。WebSocket
服务器是请求URL
中指定的类。
例如,如果您的WebSocket
服务器被称为 MyApp.MyWebSocketServer
的设计是在用户名称空间中操作,然后用于请求WebSocket
连接的URL是:
/csp/user/MyApp.MyWebSocketServer.cls
ws://127.0.0.1/dthealth/web/PHA.COM.WebSocket.cls
WebSocket事件
WebSocket
服务器的实现是从基本的%CSP.WebSocket
类派生出来的。实现以下事件的响应有三个关键方法。注意,CSP会话在调用任何这些方法之前都是解锁的。
OnPreServer (optional)
使用此方法调用应该在WebSocket
服务器建立之前执行的代码。必须在这里更改SharedConnection
属性。
Method OnPreServer() As %Status
{
//设置 SharedConnection属性
set ..SharedConnection=1
if (..WebSocketID'=""){
set ^CacheTemp.Chat.WebSockets(..WebSocketID)=""
}else {
set ^CacheTemp.Chat.Error($INCREMENT(^CacheTemp.Chat.Error),"no websocketid defined")=$HOROLOG
}
q $$$OK
}
Server (Mandatory)
WebSocket
服务。 这是WebSocket
应用程序的服务器端实现。可以使用Read()
和Write()
方法与客户机交换消息。使用EndServer()
方法从服务器端优雅地关闭WebSocket
。OnPostServer (optional)
使用此方法调用应该在WebSocket
服务器关闭后执行的代码。
WebSocket
方法
提供了以下方法
Method Read(ByRef len As %Integer = 32656,
ByRef sc As %Status,
timeout As %Integer = 86400) As %String
该方法从客户端读取len
字符。如果调用成功,状态(sc)
将返回$$$OK
,否则将返回以下错误代码之一:
$$$CSPWebSocketTimeout
读取已超时。$$$CSPWebSocketClosed
客户端已经终止了WebSocket
。
Method Write(data As %String) As %Status
此方法将数据写入客户端。
Method EndServer() As %Status
此方法通过关闭与客户端的连接来优雅地结束WebSocket
服务器。
Method OpenServer(WebSocketID As %String = "") As %Status
此方法打开现有的WebSocket
服务器。只有异步操作的WebSocket (SharedConnection=1)
可以使用此方法访问。
WebSocket属性
提供了以下属性:
SharedConnection (default: 0)
此属性确定客户端和WebSocket
服务器之间的通信是通过专用网关连接进行,还是通过共享连接池异步进行。必须在OnPreServer()
方法中设置此属性,可以按如下方式设置:
SharedConnection=0
WebSocket服务器通过专用网关连接与客户端进行同步通信。在这种操作模式下,主机连接实际上是应用程序的WebSocket
服务器的“私有”连接SharedConnection=1
WebSocket
服务器通过共享网关连接池与客户端异步通信。WebSocketID
此属性表示WebSocket
的唯一标识。SessionId
此属性表示用于创建WebSocket
的托管CSP
会话ID
。BinaryData
此属性指示网关绕过将传输的数据流解释为UTF-8
编码文本的功能,并在WebSocket
帧头中设置适当的二进制数据字段。
在将二进制数据流写入客户机之前,应该将该值设置为1。例如:
Set ..BinaryData = 1
websocket服务器示例
以下简单的WebSocket
服务器类接受来自客户机的传入连接,并简单地回显接收到的数据。超时设置为10秒,每次Read()
方法超时时,客户端都会写入一条消息。这说明了支持WebSockets
的关键概念之一:从服务器与客户端启动消息交换。
最后,如果客户端(即用户)发送了字符串exit
, WebSocket
就会优雅地关闭。
Method OnPreServer() As %Status
{
Quit $$$OK
}
Method Server() As %Status
{
Set timeout=10
For {
Set len=32656
Set data=..Read(.len, .status, timeout)
If $$$ISERR(status) {
If $$$GETERRORCODE(status) = $$$CSPWebSocketClosed {
Quit
}
If $$$GETERRORCODE(status) = $$$CSPWebSocketTimeout {
Set status=..Write(“Server timed-out at “_$Horolog)
}
}
else {
If data="exit" Quit
Set status=..Write(data)
}
}
Set status=..EndServer()
Quit $$$OK
}
Method OnPostServer() As %Status
{
Quit $$$OK
}
WebSockets服务器异步操作
前一节给出的示例演示了通过专用Caché 连接与客户机同步操作的WebSocket
服务器。当这样的连接建立后,它会在网关系统状态表单的状态列中标记为WebSocket
。使用这种模式,WebSocket
可以在托管CSP
会话的安全上下文中操作,并且可以轻松地访问与该会话关联的所有属性。
使用异步操作模式(SharedConnection=1
),一旦创建了WebSocket
对象,与客户端的后续对话就会在共享连接池中进行,此时主机连接就会被释放:来自客户机的消息通过常规的网关连接池到达Caché ,而发送到客户机的消息则通过在网关和Caché 之间建立的服务器连接池分派。
在异步模式下,WebSocket
服务器与主CSP会话分离:SessionId
属性持有托管会话ID
的值,但是不会自动创建会话对象的实例。只需在OnPreServer()
方法中设置SharedConnection
属性,就可以异步运行前面给出的示例。但是,没有必要将Caché 进程与WebSocket
永久关联起来。 Server()
可以退出(主机进程停止),而不需要关闭WebSocket
。如果保留了WebSocketID
,则可以随后在不同的Caché 进程中打开WebSocket
,并恢复与客户机的通信。
例如:
Class PHA.COM.YX.WebSocket Extends %CSP.WebSocket
{
Method OnPreServer() As %Status
{
d ##class(PHA.OP.MOB.Test).Save(..WebSocketID)
Set SharedConnection = 1
Quit $$$OK
}
Method Server() As %Status
{
Quit $$$OK
}
Method OnPostServer() As %Status
{
Quit $$$OK
}
}
注意,在OnPreServer()
方法中保留WebSocketID
供后续使用。还要注意,OnPreServer()
方法中SharedConnection
属性的设置以及服务器()方法的退出。
随后检索WebSocketID
:
Set WebSocketID = MYAPP.RETRIEVE()
与客户重新建立联系:
Set ws=##class(%CSP.WebSocketTest).%New()
Set %status = ws.OpenServer(WebSocketID)
给客户端读写
Set %status=ws.Write(message)
Set data=ws.Read(.len, .%status, timeout)
最后,从服务器端关闭WebSocket:
Set %status=ws.EndServer()
边栏推荐
- 【209】go语言的学习思想
- 6.26CF模拟赛E:价格最大化题解
- Crawler (6) - Web page data parsing (2) | the use of beautifulsoup4 in Crawlers
- 力扣刷题日记/day5/2022.6.27
- Interview summary of large factory Daquan II
- Scala basic tutorial -- 12 -- Reading and writing data
- [cloud voice suggestion collection] cloud store renewal and upgrading: provide effective suggestions, win a large number of code beans, Huawei AI speaker 2!
- NBA赛事直播超清画质背后:阿里云视频云「窄带高清2.0」技术深度解读
- Basic tutorial of scala -- 16 -- generics
- Grain Mall (I)
猜你喜欢
I always thought that excel and PPT could only be used for making statements until I saw this set of templates (attached)
Just today, four experts from HSBC gathered to discuss the problems of bank core system transformation, migration and reconstruction
MySQL common add, delete, modify and query operations (crud)
【2022年江西省研究生数学建模】冰壶运动 思路分析及代码实现
力扣刷题日记/day3/2022.6.25
Li Kou brush question diary /day1/2022.6.23
Li Kou brush question diary /day7/2022.6.29
[HCIA continuous update] network management and operation and maintenance
爬虫(6) - 网页数据解析(2) | BeautifulSoup4在爬虫中的使用
输入的查询SQL语句,是如何执行的?
随机推荐
基于C语言的菜鸟驿站管理系统
Mxnet implementation of googlenet (parallel connection network)
删除二叉搜索树中的节点附图详解
Deleting nodes in binary search tree
Li Kou brush question diary /day6/6.28
Wireshark packet capturing TLS protocol bar displays version inconsistency
TorchDrug教程
基于unity的愤怒的小鸟设计
爬虫(6) - 网页数据解析(2) | BeautifulSoup4在爬虫中的使用
Redis主从复制
Improve the accuracy of 3D reconstruction of complex scenes | segmentation of UAV Remote Sensing Images Based on paddleseg
Scala basic tutorial -- 20 -- akka
谷粒商城(一)
【2022年江西省研究生数学建模】水汽过饱和的核化除霾 思路分析及代码实现
What types of Thawte wildcard SSL certificates provide
Once the "king of color TV", he sold pork before delisting
Basic tutorial of scala -- 16 -- generics
6.26CF模拟赛B:数组缩减题解
【OpenCV入门到精通之九】OpenCV之视频截取、图片与视频互转
【210】PHP 定界符的用法