Bidirectional asynchronous data exchange in web applications
One of the main features of the modern web is called RIA by experts, which often stands for trend when web applications are close to desktop applications in terms of functionality. Nevertheless, this approximation is rather arbitrary. The vast majority of enriched web applications are still built on a request-response model. Those. events on the client side can be reflected on the server side, not the other way around. In order to realize such a banal thing like chat, you have to resort to sophisticated tricks. Thanks to Alex Russell of Dojo, we even have a name for this technique - Comet.
According to cometdaily.com, there are several solutions for emulating bidirectional data exchange between a client and a server:
In addition, you can use Flash objects or Java applets. And to complete the picture, you can mention such an ancient technique as Forever GIF.
From myself, I would add a couple of high-level solutions:
Anyway, any of these approaches is more or less a hack when you would like to use a native solution. The guys from the HTML5 working group obviously understand this situation well and that’s why the standard such as Web Sockets is included in the standard. Its description sounds like a panacea: it is tolerant to firewalls and routers, allows cross-domain communication, integrates with existing HTTP load balancers, allows the exchange of binary data, works in secure connections, etc. With all this, the Web Sockets API is very simple (see also habrahabr.ru/blogs/webdev/79038 ).
Hooray, thanks, is everyone free? But no. Currently, Web Sockets is only supported in the development version of Chrome (starting from 4.0.249.0 - www.chromium.org/getting-involved/dev-channel) and promised support in Firefox 3.7. What to do now? Obviously, you need a facade on the client side, which in the presence of Web Socket uses its "native" API, in the absence of a workaround. Such a solution could be Kaazing Websocket Gateway ( kaazing.com/download ), if it were distributed not for money, but for kindness of soul. You could use Orbited ( orbited.org ) together with io.js ( github.com/mcarter/js.io ) if you certainly need access to amqp, imap, irc, ldap, smtp, ssh, stomp, in addition to Web Sockets, telnet, xmpp and Python on the server proxying any communication. My choice: WebSocket.js ( github.com/gimite/web-socket-js ). A tiny JS library and a bridge in the form of a Flash object.
Now we only need a WebSocket server and, in our case (the backend is written in Java), Jetty is great for this, starting from version 7.0.1 (at the moment its status is almost stable, but when did it scare us?). If your server applications are written in php, you can try using phpwebsocket ( code.google.com/p/phpwebsocket ) or Phpwebsockets ( code.google.com/p/phpwebsockets ). But at your own peril and risk since both solutions are experimental.
UPDATED: Chat implementation example on phpDaemon habrahabr.ru/blogs/php/79377
I am sure the installation of Jetty will not cause you any questions, but you may encounter a problem in WebSocket.js due to the so-called cross-domain policy from Adobe. The Flash object must be allowed to open the socket on the server. The most reliable solution is to host a micro server on port 843 that responds to a policy request with the appropriate XML, as described at www.lightsphere.com/dev/articles/flash_socket_policy.html . The article even presents the simplest XML server on the pearl. However, I did not really like it, and I wrote my socket server based on the example from devzone.zend.com/article/1086 .
Now that we have Web Sockets, we can write web applications that can instantly respond to server events. It can be a notification system (notificatior) like on Facebook, it can be services for user interaction in the style of Google Waves, it can be real-time monitors (for example, users online) or integration with third-party sources of events, such as an incoming SMS or event in a desktop application. Since we expect a wide variety of events, from various sources directed to different clients, we need a reliable system for managing message flows on the server. There is a simple but elegant STOMP protocol ( stomp.codehaus.org) There are only a few commands in the API (SEND, SUBSCRIBE, UNSUBSCRIBE, BEGIN, COMMIT, ABORT, ACK, DISCONNECT) through which STOMP clients and STOMP brokers communicate. In particular, Zend Queue ( framework.zend.com/manual/en/zend.queue.stomp.html ) has a STOMP adapter. The message broker can be implemented based on Apache ActiveMQ ( activemq.apache.org ) or RabbitMQ ( www.rabbitmq.com ).
However, if you are very serious, you should pay attention to the more developed and flexible ( habrahabr.ru/blogs/webdev/62502 ) protocol AMQP ( www.amqp.org ).
Jetty, being a JBOSS container, serves Web Sockets. We only need to use another container to broadcast AMQP alerts to Web Sockets. To do this, install one of the brokers for AMPQ. ZeroMQ ( www.zeromq.org ) is considered the fastest. Qpid ( qpid.apache.org/amqp-brokers.html ) is quite popular, which is to be expected from the Apache project.
According to cometdaily.com, there are several solutions for emulating bidirectional data exchange between a client and a server:
- Long polling - the server does not immediately respond to the XHR request, but only when an event arrives in the queue addressed to this source (the “interrogator”).
- Forever frame - creates an iframe into which the server constantly adds events as they arrive.
- Script tags - dynamically created JS-blocks, which allows cross-domain communication.
- ActiveXObject (”htmlfile”) - a method available in IE and using ActiveX
- JSONRequest object ( www.json.org/JSONRequest.html ) - implements a two-way connection through two simultaneous requests (one for transmission and one for reception).
In addition, you can use Flash objects or Java applets. And to complete the picture, you can mention such an ancient technique as Forever GIF.
From myself, I would add a couple of high-level solutions:
- Bayeux protocol ( svn.cometd.com/trunk/bayeux/bayeux.html Dojo Foundation) - allows the exchange of events according to the schemes: one client - many servers, one server - many clients. In particular, it is used in the CometD project (www.cometd.com).
- BOSH protocol (http://xmpp.org/extensions/xep-0124.html XMPP standards foundation) - emulates a bi-directional data stream between a browser and a server using two synchronous HTTP connections
- Lightstreamer ( www.lightstreamer.com ) is a scalable and reliable server for “pushing” data into an “enriched” application in real time.
- APE (Ajax Push Engine) ( www.ape-project.org ) is a lightweight open source push server that has found support in MooTools, Dojo, jQuery. Read more on Habré ( habrahabr.ru/blogs/webdev/60803 ).
Anyway, any of these approaches is more or less a hack when you would like to use a native solution. The guys from the HTML5 working group obviously understand this situation well and that’s why the standard such as Web Sockets is included in the standard. Its description sounds like a panacea: it is tolerant to firewalls and routers, allows cross-domain communication, integrates with existing HTTP load balancers, allows the exchange of binary data, works in secure connections, etc. With all this, the Web Sockets API is very simple (see also habrahabr.ru/blogs/webdev/79038 ).
Hooray, thanks, is everyone free? But no. Currently, Web Sockets is only supported in the development version of Chrome (starting from 4.0.249.0 - www.chromium.org/getting-involved/dev-channel) and promised support in Firefox 3.7. What to do now? Obviously, you need a facade on the client side, which in the presence of Web Socket uses its "native" API, in the absence of a workaround. Such a solution could be Kaazing Websocket Gateway ( kaazing.com/download ), if it were distributed not for money, but for kindness of soul. You could use Orbited ( orbited.org ) together with io.js ( github.com/mcarter/js.io ) if you certainly need access to amqp, imap, irc, ldap, smtp, ssh, stomp, in addition to Web Sockets, telnet, xmpp and Python on the server proxying any communication. My choice: WebSocket.js ( github.com/gimite/web-socket-js ). A tiny JS library and a bridge in the form of a Flash object.
Now we only need a WebSocket server and, in our case (the backend is written in Java), Jetty is great for this, starting from version 7.0.1 (at the moment its status is almost stable, but when did it scare us?). If your server applications are written in php, you can try using phpwebsocket ( code.google.com/p/phpwebsocket ) or Phpwebsockets ( code.google.com/p/phpwebsockets ). But at your own peril and risk since both solutions are experimental.
UPDATED: Chat implementation example on phpDaemon habrahabr.ru/blogs/php/79377
I am sure the installation of Jetty will not cause you any questions, but you may encounter a problem in WebSocket.js due to the so-called cross-domain policy from Adobe. The Flash object must be allowed to open the socket on the server. The most reliable solution is to host a micro server on port 843 that responds to a policy request with the appropriate XML, as described at www.lightsphere.com/dev/articles/flash_socket_policy.html . The article even presents the simplest XML server on the pearl. However, I did not really like it, and I wrote my socket server based on the example from devzone.zend.com/article/1086 .
Now that we have Web Sockets, we can write web applications that can instantly respond to server events. It can be a notification system (notificatior) like on Facebook, it can be services for user interaction in the style of Google Waves, it can be real-time monitors (for example, users online) or integration with third-party sources of events, such as an incoming SMS or event in a desktop application. Since we expect a wide variety of events, from various sources directed to different clients, we need a reliable system for managing message flows on the server. There is a simple but elegant STOMP protocol ( stomp.codehaus.org) There are only a few commands in the API (SEND, SUBSCRIBE, UNSUBSCRIBE, BEGIN, COMMIT, ABORT, ACK, DISCONNECT) through which STOMP clients and STOMP brokers communicate. In particular, Zend Queue ( framework.zend.com/manual/en/zend.queue.stomp.html ) has a STOMP adapter. The message broker can be implemented based on Apache ActiveMQ ( activemq.apache.org ) or RabbitMQ ( www.rabbitmq.com ).
However, if you are very serious, you should pay attention to the more developed and flexible ( habrahabr.ru/blogs/webdev/62502 ) protocol AMQP ( www.amqp.org ).
Jetty, being a JBOSS container, serves Web Sockets. We only need to use another container to broadcast AMQP alerts to Web Sockets. To do this, install one of the brokers for AMPQ. ZeroMQ ( www.zeromq.org ) is considered the fastest. Qpid ( qpid.apache.org/amqp-brokers.html ) is quite popular, which is to be expected from the Apache project.