我正在努力理解websocket。
我在doc和这里看到了两个例子。
这两个例子都使用了无休止的循环,监听新客户端何时连接,何时做一些有趣的事情,以及何时断开连接。
我的问题是:使用websocket(无休止循环)是否比使用每x次http请求的ajax解决方案更好?
WebSocket用于实时交互通信。WebSocket连接的两端都可以发送数据,另一端将在几毫秒内接收到数据。连接保持打开状态,减少了由于连接协商而导致的延迟。
然而,它只是在某种程度上与HTTP配合得很好。也就是说,它可以很好地与支持WebSocket的代理和防火墙配合使用。WebSocket流量绝对不是HTTP流量,除了客户端的第一个数据包,它请求从HTTP切换到WebSocket协议。
另一方面,AJAX是纯HTTP。AJAX和标准web请求之间的唯一区别是,AJAX请求由客户端脚本启动,并且响应可用于同一脚本,而不是重新加载页面。
在AJAX和WebSocket中,客户端脚本都可以接收数据并在同一脚本中使用。相似之处到此为止。
WebSockets建立了一个永久的连接,双方可以随时发送数据,也可以随时安静地坐着。使用AJAX,客户端发出请求,服务器做出响应。
例如,如果您要设置一个新的消息通知系统,如果您正在使用WebSockets,那么一旦有新消息可用,服务器就会将其直接发送到浏览器。如果没有新消息,服务器将保持安静。如果您使用AJAX,客户端会定期向服务器发送一个请求,服务器总是会做出响应,要么说没有新消息,要么传递挂起的通知。服务器没有办法在它的一端启动事情,它必须等待AJAX请求。
在服务器端,事情与传统的PHP web开发范式有所不同。典型的WebSocket服务器将是作为守护进程运行的独立CLI应用程序。(如果最后一句话没有意义,请花点时间真正了解如何管理服务器。)
这意味着多个客户端将连接到同一个脚本,而像$_GET
和$_SESSION
这样的超全局变量将毫无意义。在一个小用例中概念化似乎很容易,但请记住,您很可能希望从网站的其他部分获取信息,这通常意味着使用库和框架,这些库和框架完全没有访问HTTP请求/响应模型之外的数据的概念。
因此,为了简单起见,您通常希望坚持AJAX请求和定期轮询,除非您有办法重新思考网络数据,并可能重新实现库自动化的东西,如果您希望更新标准的网络流量。
至于服务器的循环:
这不是一个繁忙的循环,而是一个IO阻塞的循环。
如果服务器尝试读取网络数据,但没有可用的数据,操作系统将阻止(暂停)脚本,然后执行其他需要执行的操作。在我的WS服务器中,在脚本返回检查并查看是否发生了应该通知我的客户端的其他新情况之前,我会阻止每次最多等待1秒的网络流量。通常,这只需要几毫秒,服务器就可以直接返回到其IO阻塞状态,等待线路上的新数据。其他一些人已经使用LibEv实现了我的服务器,这使他们能够响应网络IO之外的事件,而不必等待块超时。
几乎每个服务器都是这样做的。这就是为什么即使没有流量,Apache也可以主动侦听和服务web流量,而不会将运行Apache的每台服务器都固定在100%的CPU使用率。
最后,WebSockets是一项很棒的技术,但web库和框架并不是为了使用它们而构建的。因此,除非您在一个等待3秒完整AJAX请求的时间太长的系统中工作,否则最好使用AJAX。如果你正在编写一个多人互动游戏或聊天系统,那么你已经找到了WebSockets的完美用途。
我衷心鼓励大家学习WebSockets。。。但它并不是一颗神奇的子弹,网络中很少有部分是以人们可以真正使用它的方式设计的。
是的,套接字在很多情况下都更好。
它不是forever loop with 100% cpu utilizing
,它只是存在于每个守护进程应用程序中的liveoop。
同步accept
操作是99.99%的时间。
Ajax的心跳是更多的流量、更多的服务器CPU和内存。
我也处于学习阶段。我已经构建了一个基于php的websocket服务器,并让它与网页进行通信。也许我的2c视角是有用的。
让websocket服务器(ws)以可用资源为起点工作并没有那么困难,但接下来该怎么做呢?
WS在php的CLI版本中运行。后期模型浏览器加载一个普通的http或https页面,其中包含对ws的请求,以及该页面需要做的任何其他事情,都会发生握手。然后,浏览器和WS之间的通信就可以在任意一端随心所欲地直接进行。这是低开销的,因此快速而简单。非常酷。双方都需要理解在这个环节上所说的话——子协议。您可能需要在php和javascript中进行自己的滚动。不再有http头、url等
wss是php的一个长寿命、有状态的实例(与apache等非常不同,后者在发送页面时会忘记您)。整个应用程序可以在wss实例中运行,保持自身和每个连接的客户端的状态。以前有人说php太漏洞百出,不适合长期使用,但我现在已经听不到了。但我相信你还是要小心记忆。
然而,作为单个php实例,客户端实例之间没有通常的分离。例如,类中的静态信息与每个类实例共享,从而与每个客户端共享。因此,对于一个与一堆客户端共享数据的单用户风格的应用程序来说,这是非常棒的。我可以看到Ajax类型的调用可以用这种方式替换,但如果应用程序仍然必须重建状态来为每个客户端提供服务,然后释放它来节省资源,这似乎会减少优势。
更进一步,为客户端保留真正有状态的实例似乎是可能的下一步。复制传统的基于会话的系统是一种可能性,或者派生新的php解释器,并通过套接字等处理父级和子级之间的通信。但这将需要每个客户端的资源,这将严重限制任何非平凡的应用程序。
或者,也许可以把应用程序的大部分放在家长身上,让孩子们只做客户端特有的事情。或者将应用程序设计分解为可以通过套接字直接通信的小型独立单元。套接字通信现在似乎很流行。
正如Ghedpunk在很多方面所说,现实世界似乎还没有准备好实现web套接字概念的全部潜力,但它肯定可以取代Ajax。服务器在不被要求的情况下发送的额外优势开辟了以前难以考虑的新可能性。