为什么Web Sockets不使用SOAP?

7
首先,我没有敌意或疏忽之意,只是想了解人们的想法。我正在研究客户端和服务器之间的双向通信;客户端是一个Web应用程序。目前,我有几个选择:据我所听,微软专有的双工绑定不可靠且不自然;Comet和WebSocket(适用于支持的浏览器)。
我知道这个问题已经以其他方式在这里提出过,但我有一个更具体的问题要问。考虑到WebSocket是客户端的,客户端代码位于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花费了很长时间才得到普及...我们是否在错误的方向上浪费了大量精力?您有何想法?

6个回答

20
听起来你还没有完全理解Websockets的概念。例如,你说:

考虑到Websockets是客户端

这并不是事实,sockets有两个方面,你可以将它们视为服务器和客户端,但一旦建立连接,区别就模糊了——你也可以认为客户端和服务器是“对等”的,每个都可以在任何时候向连接它们的管道(socket连接)中写入或读取。我猜你会从了解HTTP在TCP之上如何工作中受益,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

希望能对你有所帮助。


5
堆叠部分并不完全正确。虽然SOAP在大多数情况下是通过HTTP发送的,但WSDL允许定义任意绑定。由于WSDL的设计非常可扩展,因此可以定义和实现基于Websockets的SOAP绑定。这样,它就会变成SOAP-> Websocket-> TCP,其中SOAP只是消息编码格式。即使在本答案中提供的示例中,通过websocket发送的数据也必须以某种方式进行编码,例如作为JSON。因此,正确的类比应该是JSON-> Websocket-> TCP与SOAP-> Websocket-> TCP与SOAP-> HTTP-> TCP。 - vanto
@vanto,是否有“JSON on WebSocket on TCP”这种JSON编码标准?类似于SOAP使用XML的方式? - Franklin Yu

4
JavaScript允许客户端通过XMLHttpRequest与HTTP进行通信。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项目包括wsproxy(http://github.com/kanaka/noVNC/tree/master/utils/),用于在WebSockets和原始TCP套接字之间进行代理。 - kanaka

3
正如您所指出的,WebSockets具有低开销。与AJAX / Comet相比,开销类似于普通TCP套接字:每个帧只多两个字节。

为什么使用低级别而不是某种内置的RPC功能?一些想法:

  • 将现有的RPC协议“分层”在低级套接字协议上并不难。但如果假定了RPC开销,就不能反过来构建低级连接。

  • 在服务器端添加WebSocket支持对于多种语言而言相当简单。有效负载只是一个UTF-8字符串,几乎每种语言都内置了高效的支持。但RPC机制则不然。如何处理Javascript和目标语言之间的数据类型转换?需要在Javascript端添加类型提示吗?变长参数和/或参数列表怎么办?如果语言没有好的解决方案,是否需要构建这些机制?等等。

  • 它会模仿哪种RPC机制?你会选择现有的(SOAP、XML-RPC、JSON-RPC、Java RMI、AMF、RPyC、CORBA)还是全新的?

  • 一旦客户端支持普及,那么许多使用普通TCP套接字的服务将添加WebSocket支持(因为这很容易)。如果WebSocket基于RPC,情况并非如此。一些现有服务可能会添加RPC层,但大部分WebSocket服务都将从头开始创建。

对于我的noVNC项目(使用JavaScript、Canvas和WebSockets的VNC客户端),WebSockets的低开销特性对于实现合理的性能至关重要。在VNC服务器包含WebSockets支持之前,noVNC包括wsproxy,这是一个通用的WebSockets到TCP套接字代理。
如果您正在考虑实现交互式Web应用程序,并且尚未决定服务器端语言,则建议查看Socket.IO,这是一个针对node(使用Google的V8引擎的服务器端JavaScript)的库。
除了node的所有优势(两侧使用相同的语言,非常高效,强大的库等),Socket.IO还提供了以下几个功能:
提供处理连接的客户端和服务器框架库。 检测客户端和服务器都支持的最佳传输方式,包括(从最好到最差):本地WebSockets、使用Flash模拟的WebSockets、各种AJAX模型。 无论使用哪种传输方式,保持一致的接口。 自动编码/解码Javascript数据类型。 由于双方使用相同的语言和本机类型,因此在Socket.IO上创建RPC机制并不困难。

1

WebSocket通过允许服务器发起请求,使Comet和所有其他HTTP推送类型技术变得可读。它是一种沙盒套接字,并为我们提供了有限的功能。

然而,该API足够通用,以便框架和库作者可以以任何希望的方式改进接口。例如,您可以在WebSockets之上编写一些RPC或RMI样式的服务,允许在网络上传输对象。现在,在内部,它们被序列化为某种未知格式,但服务用户不需要知道也不关心。

因此,从规范作者的角度考虑,从

mysocket.send("AFunction|withparameters|segmented");

myServerObject.AFunction("that", "makessense");

相对而言,编写一个小的包装器来处理WebSockets的序列化和反序列化使得编程相对容易。但是反过来进行编程意味着规范作者需要创建一个更复杂的API,这将导致编写基于其之上的代码的基础更加薄弱。


0

WebSocket JSR是由许多不同议程的各方(Oracle、Apache、Eclipse等)协商达成的。很幸运他们停留在消息传输层,没有涉及更高级别的结构。如果您需要Java到JavaScript RMI,可以查看FERMI Framework


0

我遇到了同样的问题,需要做类似于call('AFunction', 'foo', 'bar')而不是序列化/反序列化每个交互。我的首选也是将大部分代码留在服务器上,只使用JavaScript处理视图。WebSockets更适合,因为它自然支持双向通信。为了简化我的应用程序开发,我在WebSockets之上构建了一个层,以进行远程方法调用(如RPC)。

我已经发布了http://sourceforge.net/projects/rmiwebsocket/RMI/RPC库。一旦网页和servlet之间建立了通信,您可以在任何方向上执行调用。服务器使用反射调用服务器端对象中的适当方法,客户端使用JavaScript的'call'方法调用客户端对象中的适当函数。该库使用Jackson来处理各种Java类型与JSON之间的序列化/反序列化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接