即时通讯技术的发展与网络套接字的技术实践

时间:2020-10-20

OpenMeetings

即时通讯技术的发展与网络套接字的技术实践

 前言

 为什么网络即时通讯技术如此重要?我们生活在一个实时的世界,所以网络最自然的状态应该是实时的。用户需要实时通信、数据和搜索。我们对互联网上实时信息的要求越来越高。如果信息或消息在几分钟的延迟后被更新,那简直让人无法忍受。如今,许多大公司(如谷歌、脸书和推特)关注实时网络并提供实时服务。实时网络是现在和将来最热门的话题之一。

 相关技术文章

 Web即时通讯初学者贴纸:

 初学者的帖子:详细解释网上即时通讯技术的原理

 关于Ajax短轮询:

 在这一领域寻找信息是没有意义的。除非你欺骗顾客,否则请考虑其他三个方案。

 有关Comet技术的详细介绍,请参考:

 慧星技术详解:基于HTTP长连接的网络实时通信技术

 网络即时消息:对长连接和长轮询的详细解释

 网络即时消息:消息的即时性可以在没有网络套接字的情况下实现

 开源Comet服务器:支持数百万并发的网络即时消息解决方案

 有关WebSocket的详细介绍,请参见:

 网络插座的详细说明(一):对网络插座技术的初步理解

 WebSocket详细说明(二):技术原理、代码演示和应用案例

 网络套接字的详细解释(3):网络套接字通信协议的深入细节

 网络即时通讯技术的发展及网络套接字和社交网络的技术实践

 套接字简介。IO:一个支持网络即时通讯的框架

 socket.io和websocket之间是什么关系?有什么不同?》

 有关上交所的详细介绍,请参见:

 SSE技术的详细说明:一种新的HTML5服务器推送事件技术

 有关更多网络即时消息文章,请参见:

 http://www.52im.net/forum.php? mod =收集和行动=视图和ctid=15

 网络即时通讯的发展历史

 传统的网站是基于HTTP请求/响应模型的:客户端请求一个新页面,服务器将内容发送给客户端,客户端在请求另一个页面时再次发送请求。

 后来,有人提出了AJAX,它使页面的体验更加“动态”,并且可以在后台向服务器发起请求。但是,如果服务器有更多的数据要推送到客户端,在加载页面后就不可能直接从服务器向客户端发送数据。实时数据无法推送到客户端。

 为了解决这个问题,人们提出了许多解决方案。最简单(暴力)的方案是轮询:每隔一段时间,服务器就会请求新数据。这让用户觉得应用程序是实时的。事实上,这将导致延迟和性能问题,因为服务器必须每秒处理大量的连接请求,并且每个请求都将具有带有HTTP报头信息的TCP三次握手。尽管轮询仍在许多应用程序中使用,但它不是最佳解决方案。有关轮询技术的详细说明,请参见文章“网络即时消息:对HTTP长连接和长轮询的详细说明”。

 后来,随着彗星技术的出现,出现了许多更先进的解决方案。这些技术方案包括永久帧、XHR多部分、html文件和长轮询。长轮询意味着客人

 客户端发起到服务器的XHR连接,该连接从不关闭,并且对于客户端,该连接总是被挂起。当服务器有新数据时,它会及时向客户端发送响应,然后关闭连接。然后重复整个过程,以这种方式实现“服务器推送”。参见文章彗星技术详细说明:基于长连接的网络实时通信技术。

 Comet技术是一种非标准的黑客技术,正因为如此,浏览器兼容性成了一个问题。首先,性能问题无法解决。到服务器的每个连接都携带完整的HTTP头信息。如果你的申请需要低延迟,这将是一个棘手的问题。当然,这并不是说彗星本身有问题,因为在没有其他选择之前,彗星是我们唯一的选择。

 浏览器插件(如闪存)和Java也用于实现服务器推送。他们可以基于TCP直接与服务器建立套接字连接,非常适合将实时数据推送到客户端。问题是,并不是所有的浏览器都安装了这些插件,它们经常被防火墙阻挡,尤其是在企业网络中。

 现在,HTML5规范为我们准备了一个替代方案。然而,这个规范稍微提前了一点,一些或更多的最新浏览器不支持它,尤其是IE。然而,对于现在的许多开发者来说,HTML5的WebSocket必将成为未来的趋势,值得进一步的研究和理解。参见网络套接字详细说明(一):对网络套接字技术的初步了解,网络套接字详细说明(二):技术原理、代码演示和应用案例,网络套接字详细说明(三):深入的网络套接字通信协议细节。

 网络插座的技术实践

 WebSocket(http://dev.w3.org/html5/websockets)是HTML5规范的一部分,它提供基于TCP的双向全双工套接字连接。这意味着服务器可以直接将数据推送到客户端,而不需要开发人员求助于长轮询或插件,这是一个很大的进步。虽然有些浏览器不支持网络套接字,但是对于那些不支持网络套接字的浏览器,它们可以通过使用一些愚蠢的方法来降级,比如Comet或者polling。

 与以前的服务器推送技术相比,WebSocket具有很大的优势,因为WebSocket是全双工的,不基于HTTP,并且一旦建立连接就不会中断。Comet面临的真正问题是HTTP太大,每个请求都携带完整的HTTP头信息。它包含许多无用的TCP握手,因为HTTP是比TCP更高级的网络协议。

 当使用WebSocket时,一旦服务器和客户端之间的握手完成,信息就可以自由地从两端流入流出,而不会附加无用的HTTP头信息。这大大减少了带宽占用并提高了性能。因为连接总是处于活动状态,所以服务器可以在需要更新时立即向客户端发送新数据(无需客户端首先请求,服务器再次响应)。此外,连接是双工的,因此客户端也可以向服务器发送数据,而不需要额外的HTTP头。

 下面这段话来自谷歌的伊恩·希克森,他是HTML5规范团队的负责人,他对WebSocket的描述如下:

 将千字节的数据减少到2字节…并将延迟从150毫秒减少到50毫秒,这种优化跨越了不止一个数量级。事实上,只有这两个优化足以让谷歌相信,WebSocket将为产品带来不同寻常的用户体验。

 现在让我们来看看哪些浏览器支持WebSocket:

 工业工程> = 10

 铬> = 4

 狩猎> = 5

 iOS >= 4.2

 火狐> = 4*

 歌剧> = 11*

 检测浏览器是否支持WebSocket也非常简单和直接:

 支持12var(“窗口中的WebSocket”);如果(支持)警报(“支持网络套接字”);

 从长远来看,浏览器的WebSocket应用编程接口非常清晰和合理。您可以使用WebSocket类实例化一个新的套接字,它需要传入服务器的结束地址,在本例中,ws://example.com:

 1var socket =新的WebSocket(" ws://example . com ");

 然后我们需要添加事件监听这个套接字:

 123456//建立连接插座。on open = function () {/*...*/}//通过连接套接字发送一些新数据。on message =函数(数据){/*...*/}//关闭连接插座。onclose = function () {/*...*/}

 当服务器发送一些数据时,将触发onmessage事件。同样,客户端也可以调用send()

 函数向服务器返回数据。显然,我们应该在建立连接并触发onopen事件后调用它:

 123456 socket . on message = function(消息){console.log("新数据-",消息);};socket . onopen = function(){ socket . send(“为什么,你好”)。};

 发送和接收消息只支持字符串格式。但是您可以轻松地在字符串和JSON数据之间进行转换,因此您可以创建自己的协议:

 123456789 var RPC = { test:function(arg 1,arg2) { /*...*/} };Socket.onmessage =函数(数据){//Parse JSONvar消息= JSON.parse(数据);//调用RPC函数。方法]。应用(RPC,消息。args);};

 在这段代码中,我们创建了一个远程过程调用(RPC)脚本,服务器可以发送一些简单的JSON来调用客户端的函数,就像下面的代码行一样:

 1{ "方法":"测试","参数":[1,2]}

 请注意,这里的调用仅限于rpc对象。这主要是出于安全原因。如果允许在客户端执行任意的JavaScript代码,黑客就会利用这个漏洞。您可以调用close()函数来关闭此连接:

 1var socket =新的WebSocket(“ws://localhost:8000/server”);

 您一定注意到了,当我们实例化一个WebSocket时,我们使用了特定于WebSocket的协议前缀ws://而不是http://。WebSocket还支持加密连接,这要求TLS前缀为wss://。默认情况下,WebSocket使用端口80建立未加密连接,使用端口443建立加密连接。您可以通过将自定义端口添加到该网址来覆盖默认配置。请记住,并非所有端口都可以被客户端使用,一些非常规端口很容易被防火墙拦截。

 现在,你可能会想,“我不能在项目中使用网络套接字,因为标准还没有形成,并且IE不支持网络套接字”。这个想法没有错。幸运的是,我们有一个解决方案。Https://github.com/gimite/web-socket-js是一个基于AdobeFlash的网络套接字。有了这个库,可以在不支持WebSocket的浏览器中进行优雅的降级。毕竟,几乎所有的浏览器都安装了闪存插件。基于闪存的SocketAPI与HTML5标准规范完全相同,因此当WebSocket的浏览器兼容性更好时,只需简单地移除库,而无需对代码进行任何修改。

 尽管客户端应用编程接口非常简洁直接,但服务器端的情况却不同。WebSocket协议包含两个不兼容的草案协议:草案75(http://goo.gl/cgSjp)和草案76 (http://goo.gl/2u78y)。服务器需要通过检测客户端使用的连接握手类型来确定使用哪种协议草案。

 网络套接字首先向服务器发起一个HTTP“升级”请求。如果您的服务器支持网络套接字,它将执行网络套接字握手并初始化连接。升级请求包含原始域的信息(请求来源的域名)。客户端可以与任何域名建立WebSocket连接,并且只有服务器将决定哪些客户端可以与它建立连接。通常的做法是将域名连接到一个白名单中。

 在WebSocket设计之初,设计者希望只要初始连接使用常用的端口和HTTP头字段,它们就能与防火墙和代理软件和谐共存。然而,理想是充实的,而现实是渺小的。一些代理软件修改了WebSocket的“升级”请求的标题信息,违反了协议规则。事实上,协议草案(版本76)的最新更新无意中破坏了与反向代理和网关的兼容性。为了更好、更成功地使用WebSocket,以下是一些步骤:

 使用安全的网络套接字连接。代理软件不会篡改加密连接,您发送的数据是加密的,不容易被他人窃取。

 在网络套接字服务器前使用TCP负载平衡器,而不是HTTP负载平衡器,除非HTTP负载平衡器宣称它支持网络套接字。

 不要假设浏览器支持网络套接字,尽管浏览器支持网络套接字只是时间问题。诚然,如果不能快速建立连接,那么快速而优雅的降级由Comet和轮询来处理。

 那么,如何在服务器端选择解决方案呢?幸运的是,许多语言都支持WebSocket,例如Ruby、Python和Java。有必要再次确认每个实现是否支持最新的草案协议版本76,因为大多数客户端都支持该协议。

 Node.js

 ─插座。IO(http://socket.io)

 -法国兴业银行(https://github.com/sockjs)

 -节点-网络套接字-服务器(http://github.com/miksago/node-websocket-server)

 红宝石

 事件机器(http://github.com/igrigorik/em-websocket)

 抽筋(https://github.com/lifo/cramp)

 阳光(http://rainbows.rubyforge.org/sunshowers/)

 大蟒

 扭曲(http://github.com/rlotun/txWebSocket)

 阿帕奇模块(http://code.google.com/p/pywebsocket)

 PHP

 PHP-Websocket(http://github.com/nicokaiser/php-websocket)

 爪哇岛

 码头(http://www.eclipse.org/jetty)

 雄猫7、雄猫8(https://tomcat.apache.org)

 谷歌围棋

 土著(http://code.google.com/p/go)

 节点与套接字的技术实践。信息作战

 在上表中,node . js(http://nodejs.org)是一个新成员,也是目前最受关注的新技术。Node.js是一个事件驱动的JavaScript服务器,它使用谷歌的V8引擎。正因为如此,Node.js速度非常快,而且它还可以像WebSocket服务器一样解决大量并发连接的资源消耗问题。

 Http://socket.io/是一个Node.js库,它实现了网络套接字。最有趣的事情不仅限于此。让我们看看官方网站上的宣传文字:

 套接字的目标。信息作战是在每个浏览器和移动设备上建立一个实时应用程序,减少各种传输机制之间的差异。

 如果环境支持网络套接字,套接字。IO将尝试使用网络套接字,如果有必要,它将降级为使用其他传输方法。

 套接字支持的传输模式。这里列出了IO,这是非常全面的,所以WebSocket。IO可以实现更好的浏览器兼容性:

 网络插座

 Adobe闪存插座

 ActiveX HTMl文件

 基于多部分编码发送xhr(xhr采用多部分编码)

 基于长期投票的XHR

 JSONP轮询(用于跨域场景)

 套接字的浏览器支持。信息作战非常全面。“服务器推送”的实现是一个众所周知的问题,但是套接字。信息作战小组为你解决了这些麻烦。信息作战确保它与大多数浏览器兼容。

 套接字的兼容性。输入输出浏览器如下:

 狩猎> = 4

 铬> = 5

 工业工程> = 6

 ios

 火狐> = 3

 歌剧> = 10.61

 尽管插座。在服务器端实现的IO最初是基于Node.js的,现在可以用其他语言实现,比如Ruby(Rack)(http://github.com/markjeee/Socket.IQ-rack)和Python(龙卷风)

 Https://github.com/MrJoes/tornadio,·爪哇(http://code.google.com/p/socketio-java)和

 谷歌官方网站(http://github . com/madari/go-socket . io).

 看看套接字的API。写作非常简单直接。客户端的应用编程接口和网络套接字的应用编程接口看起来非常相似:

 12345678var socket =新io。套接字();socket.on(“连接”),函数(){ socket . send(‘hi!’));});socket.on(“消息”),函数(数据){alert(数据);});socket.on("disconnect ",函数(){ });

 背景是套接字。IO将选择使用最佳的传输方法。如自述文件中所述,“您可以使用套接字。在任何地方构建实时应用的信息作战”。

 如果你想找到一个比Socket更先进的解决方案。IO,您可以注意到jugger naut(http://github . com/maccman/jugger naut),它是基于socket.io的。juggernaut包含一个信道接口:客户端可以订阅信道监控,服务器可以向信道发布消息,这称为订阅/发布(http://en.wikipedia.org/wiki/PubSub)模式。这个库可以灵活地扩展到不同的客户端和实现环境,例如TLS。

 如果你需要一个虚拟主机的解决方案,你可以参考http://pusherapp.com/. Pusher可以帮助你摆脱复杂的服务器管理事务,这样你就可以专注于有意义的部分:Web应用程序的开发。客户端的实现非常简单,只需将JavaScript文件引入页面并订阅频道监控。当消息被发布时,只需向RESTAPI发送一个HTTP请求。