为啥 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?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 C# 中更改soap xml Web 服务?

我应该使用 Web Sockets 吗?

使用 Oracle 10 中具有复杂类型的 SOAP Web 服务 WSDL

尽管 REST 具有以下优势,为啥 Google 仍使用大量 SOAP?

在到 WCF Web 服务的 SOAP 消息中,如何将 KeyIdentifier 直接放在 SecurityTokenReference 中(内联,不使用引用令牌)

在不依赖 app.config 的情况下使用 SOAP Web 服务