为啥 Web Sockets 不使用 SOAP?
Posted
技术标签:
【中文标题】为啥 Web Sockets 不使用 SOAP?【英文标题】:Why doesn’t Web Sockets use SOAP?为什么 Web Sockets 不使用 SOAP? 【发布时间】:2010-10-24 07:40:20 【问题描述】:首先,我无意敌视或疏忽,只是想了解人们的想法。我正在研究客户端和服务器之间的双向通信;客户端是一个 Web 应用程序。在这一点上,我有几个选择:MS 专有的双工绑定,据我所知不可靠和不自然:comet 和 web 套接字(用于支持的浏览器)。
我知道这个问题已在此处以其他方式提出,但我对该方法有一个更具体的问题。考虑到 Web 套接字是客户端的,客户端代码位于 javascript 中。是否真的打算直接在 JavaScript 中构建大量应用程序?为什么 W3C 不在 Web 服务中这样做?如果我们能够使用 SOAP 来提供合同并定义事件以及所涉及的现有消息传递,那不是更容易吗?到目前为止,感觉就像棍子的短端。
为什么不让它变得简单,利用 JS 的动态特性,将大量代码留在它所属的地方......在服务器上?
代替
mysocket.send("AFunction|withparameters|segmented");
我们可以说
myServerObject.AFunction("that", "makessense");
而不是
...
mysocket.onmessage = function() alert("yay! an ambiguous message");
...
我们可以说
...
myServerObject.MeaningfulEvent = function(realData) alert("Since I have realistic data...."); alert("Hello " + realData.FullName);
...
html 5 花了很长时间才站稳脚跟……我们是否在错误的方向上浪费了大量精力?想法?
【问题讨论】:
【参考方案1】:在我看来,您似乎还没有完全掌握 Websockets 的概念。比如你说:
考虑到 web 套接字是客户端的
情况并非如此,套接字有 2 个面,您可以将它们视为服务器和客户端,但是一旦建立连接,区别就会变得模糊 - 您也可以将客户端和服务器视为“对等方” " - 每个人都可以随时写入或读取连接它们的管道(套接字连接)。我怀疑你会从了解更多关于基于 TCP 的 HTTP 工作中受益 - WebSockets 在这种方式上类似于/类似于 HTTP。
关于 SOAP / WSDL,从围绕 TCP / WebSocket / HTTP 的对话的角度来看,您可以将所有 SOAP / WSDL 对话视为与 HTTP 相同(即正常的网页流量)。
最后,请记住网络编程的堆叠性质,例如 SOAP/WSDL 看起来像这样:
SOAP/WSDL
--------- (sits atop)
HTTP
--------- (sits atop)
TCP
WebSocket 看起来像这样
WebSocket
--------- (sits atop)
TCP
HTH。
【讨论】:
好吧,堆叠部分并不完全正确。尽管 SOAP 在大多数情况下是通过 HTTP 发送的,但 WSDL 允许定义任意绑定。由于 WSDL 在设计上具有很强的可扩展性,因此可以定义和实现 SOAP over Websockets 绑定。那样它将是 SOAP -> Websocket -> TCP,其中 SOAP 只是消息编码格式。即使在这个答案中勾画的示例中,通过 websocket 发送的数据大多数都以某种方式编码,例如作为 JSON。所以正确的类比是 JSON -> Websocket -> TCP vs. SOAP -> Websocket -> TCP vs. SOAP -> HTTP -> TCP。 @vanto 对于“TCP 上的 WebSocket 上的 JSON”有没有这样的 JSON 编码标准?类似于 SOAP 对 XML 所做的事情?【参考方案2】:JavaScript 允许客户端通过 HTTP 与 XMLHttpRequest 进行通信。 WebSockets 扩展此功能以允许 JavaScript 进行任意网络 I/O(不仅仅是 HTTP),这是一个逻辑扩展,允许移植需要使用 TCP 流量(但可能不使用 HTTP 协议)的各种应用程序到 JavaScript。我认为随着应用程序继续向云迁移,HTML 和 JavaScript 支持桌面上可用的所有内容是相当合乎逻辑的。
虽然服务器可以代表 JavaScript 客户端执行非 HTTP 网络 I/O 并通过 HTTP 进行通信,但这并不总是最合适或最有效的做法。例如,在尝试制作在线 SSH 终端时增加额外的往返成本是没有意义的。 WebSockets 使 JavaScript 可以直接与 SSH 服务器对话。
至于语法,部分是基于XMLHttpRequest的。正如在另一篇文章中所指出的,WebSockets 是一个相当低级的 API,可以包装在一个更易于理解的 API 中。 WebSockets 支持所有必要的应用程序比它具有最优雅的语法更重要(有时专注于语法会导致更多限制性的功能)。库作者始终可以使这个非常通用的 API 更易于其他应用程序开发人员管理。
【讨论】:
您不能完全使用 WebSockets 直接连接到原始套接字(有一个握手和两个字节的帧)。我的 noVNC 项目包括在 WebSocket 和原始 TCP 套接字之间代理的wsproxy
(github.com/kanaka/noVNC/tree/master/utils)。【参考方案3】:
如您所述,WebSockets 开销低。开销类似于普通 TCP 套接字:与 AJAX/Comet 的数百个字节相比,每帧仅多两个字节。
为什么是低级而不是某种内置的 RPC 功能?一些想法:
采用现有的 RPC 协议并将其分层在低级套接字协议上并不难。如果假设有 RPC 开销,则不能反其道而行之,建立低级连接。
WebSockets 支持相当简单添加到服务器端的多种语言。有效负载只是一个 UTF-8 字符串,几乎每种语言都内置了对此的有效支持。 RPC 机制没有那么多。您如何处理 Javascript 和目标语言之间的数据类型转换?您是否需要在 Javascript 端添加类型提示?可变长度参数和/或参数列表呢?如果语言没有好的答案,你会建立这些机制吗?等等。
它将以哪种 RPC 机制为模型?您会选择现有的(SOAP、XML-RPC、JSON-RPC、Java RMI、AMF、RPyC、CORBA)还是全新的?
一旦客户端支持相当普遍,那么许多具有普通 TCP 套接字的服务将添加 WebSockets 支持(因为添加起来相当简单)。如果 WebSockets 是基于 RPC 的,情况就不一样了。一些现有的服务可能会添加一个 RPC 层,但大部分 WebSockets 服务都是从头开始创建的。
对于我的noVNC 项目(仅使用 Javascript、Canvas、WebSockets 的 VNC 客户端),WebSockets 的低开销特性对于实现合理的性能至关重要。在 VNC 服务器包含 WebSockets 支持之前,noVNC 包含 wsproxy,它是一个通用的 WebSockets 到 TCP 套接字代理。
如果您正在考虑实现交互式 Web 应用程序并且尚未决定使用服务器端语言,那么我建议您查看 Socket.IO,它是 node 的库(使用 Google 的 V8 引擎的服务器端 Javascript )。
除了 node 的所有优点(双方语言相同、非常高效、强大的库等)之外,Socket.IO 还为您提供了以下几点:
提供用于处理连接的客户端和服务器框架库。
检测客户端和服务器都支持的最佳传输。传输包括(从最好到最差):原生 WebSocket、使用 Flash 仿真的 WebSocket、各种 AJAX 模型。
无论使用何种传输方式,接口都一致。
Javascript 数据类型的自动编码/解码。
在 Socket.IO 之上创建 RPC 机制并不难,因为双方都是具有相同原生类型的相同语言。
【讨论】:
【参考方案4】:WebSocket 允许来自服务器的请求,使 Comet 和所有其他 HTTP 推送类型技术清晰易读。它是一种沙盒套接字,给我们有限的功能。
但是,API 足够通用,框架和库作者可以按照他们想要的方式改进界面。例如,您可以在 WebSockets 之上编写一些 RPC 或 RMI 样式的服务,以允许通过网络发送对象。现在在内部它们以某种未知格式被序列化,但服务用户不需要知道也不关心。
所以从规范作者 POV 思考,从
mysocket.send("AFunction|withparameters|segmented");
到
myServerObject.AFunction("that", "makessense");
相对简单,需要围绕 WebSocket 编写一个小包装器,以便对应用程序不透明地进行序列化和反序列化。但是反过来意味着规范作者需要制作一个更复杂的 API,这使得在其上编写代码的基础更加薄弱。
【讨论】:
【参考方案5】:我遇到了同样的问题,我需要执行call('AFunction', 'foo', 'bar')
之类的操作,而不是对每个交互进行序列化/反序列化。我的偏好还是将大部分代码留在服务器上,只使用 Javascript 来处理视图。 WebSockets 更适合,因为它对双向通信的自然支持。为了简化我的应用程序开发,我在 WebSockets 之上构建了一个层来进行远程方法调用(如RPC
)。
我在http://sourceforge.net/projects/rmiwebsocket/ 上发布了RMI/RPC
库。一旦在网页和 servlet 之间建立了通信,您就可以在任一方向执行调用。服务器使用反射调用服务器端对象中的适当方法,客户端使用 Javascript 的“调用”方法调用客户端对象中的适当函数。该库使用Jackson 来处理各种Java 类型与JSON 的序列化/反序列化。
【讨论】:
【参考方案6】:WebSocket JSR 是由多方(Oracle、Apache、Eclipse 等)协商的,它们的议程各不相同。他们在消息传输级别停止并留下更高级别的构造也很好。如果您需要的是 Java 到 JavaScript RMI,请查看FERMI Framework。
【讨论】:
以上是关于为啥 Web Sockets 不使用 SOAP?的主要内容,如果未能解决你的问题,请参考以下文章
使用 Oracle 10 中具有复杂类型的 SOAP Web 服务 WSDL
尽管 REST 具有以下优势,为啥 Google 仍使用大量 SOAP?
在到 WCF Web 服务的 SOAP 消息中,如何将 KeyIdentifier 直接放在 SecurityTokenReference 中(内联,不使用引用令牌)