Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Introduction
In most web application, the client send a request to a server only when refreshing the entire page. Ajax refers to the ability to asynchronously talk to the server, without triggering a full-screen refresh. The term Comet is used to describe exchanges between a client and a server in which the server, rather than the client, initiates the contact. This is discordant with the nature of HTTP in wich: 1. Communication between the client and the server is always initiated by the client. 2. Connection between the client and the server are transient. The server do not maintain any long-term state information regarding the client. The second assumption is broken by the introduction of the HTTP session. Comet collide with the rst assumption and allow the server to decide when it should contact the client. Although this, a number of workarounds can be used to implement Comet over classic HTTP. The simplest way is the following: - The client makes a regular request to the server when the document is nished loading (onLoad JavaScript attibute). - The server suspends the request until it doesnt have a notication to the client. At that point it sends back the response. - When the client receives the response makes a new request to the server. Comet can be implemented in Java using Grizzly Comet[1]. The Grizzly framework has been designed to help developers to write scalable server applications in the JavaTM programming language. Grizzly Comet is a framework build on top of the Grizzly that supports Comet model. The paper is organized as follows: a brief description of source code in Section 2, followed by experimental results in Section 3. 1
2
2.1
Implementation
Server side
The main class is pretty straight forward. Creates the server, installs the HttpHandler to service requests made to /echo, and starts the server. Moreover launches a new ConsoleListener thread that will listen the console for command.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public s t a t i c void main ( S t r i n g [ ] a r g s ) { Response [ ] r e s p o n s e T o H a n d l e = new Response [ 1 ] ; HttpServer s e r v e r = HttpServer . createSimpleServer ( ) ; CounterHandler h a n d l e r= new CounterHandler ( r e s p o n s e T o H a n d l e ); s e r v e r . g e t S e r v e r C o n f i g u r a t i o n ( ) . addHttpHandler ( h a n d l e r , / echo ) ; C o n s o l e L i s t e n e r l i s t e n e r = new C o n s o l e L i s t e n e r ( responseToHandle ) ; Thread t = new Thread ( l i s t e n e r ) ; try { server . start () ; t . start () ; } catch ( E x c e p t i o n e ) { System . e r r . p r i n t l n ( e ) ; } }
CounterHandler class serves the incoming HTTP GET requests through the service method. In particular it stores the request in the array responseToHandle and suspends it.
1 2 3 4 5 6 7 8 9 10 11 12 13 public c l a s s CounterHandler extends HttpHandler { private Response [ ] r e s p o n s e T o H a n d l e ; public CounterHandler ( Response [ ] responseToHandle = l i s t ; } l i s t ){
public void s e r v i c e ( Request req , Response r e s p ) throws Exception { responseToHandle [ 0 ] = resp ; r e s p . suspend ( ) ; } }
ConsoleListener thread listens the console for command. More precisely it sends a burst of response to the waiting request, resuming it. Obviously only the rst resume command will succede, and all the others in the burst will fail, until a new request will be scheduled.
1 2 3 4 5 6 7 8 9 public c l a s s C o n s o l e L i s t e n e r implements Runnable { public s t a t i c f i n a l i n t BURST SIZE = xxx ; private Response [ ] r e s p o n s e T o H a n d l e ; public C o n s o l e L i s t e n e r ( Response [ ] responseToHandle = l i s t ; } l i s t ){
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
public void run ( ) { while ( true ) { B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r ( new InputStreamReader ( System . i n ) ) ; S t r i n g s = br . r e a d L i n e ( ) ; i f ( s . equals ( start ) ) burst () ; } } public void b u r s t ( ) { f o r ( i n t j =0; j <BURST SIZE ; j ++){ try { Response r e s = r e s p o n s e T o H a n d l e [ 0 ] ; r e s . resume ( ) ; } catch ( E x c e p t i o n e ) {} } } }
2.2
Client side
The client simply sends a request to the server and waits for a response. As soon as it receives a reply, updates a counter and sends a new request.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 <html> <head> ... < s c r i p t type= t e x t / j a v a s c r i p t > v a r myRequest = n u l l ; var counter = 0 ; f u n c t i o n CreateXmlHttpReq ( h a n d l e r ) { v a r xmlhttp = n u l l ; try { xmlhttp = new XMLHttpRequest ( ) ; } catch ( e ) { try { xmlhttp = new ActiveXObject ( Msxml2 .XMLHTTP ) ; } catch ( e ) { xmlhttp = new ActiveXObject ( M i c r o s o f t .XMLHTTP ) ; } } xmlhttp . o n r e a d y s t a t e c h a n g e = h a n d l e r ; r e t u r n xmlhttp ; } f u n c t i o n myHandler ( ) { i f ( myRequest . r e a d y S t a t e == 4 ) { c o u n t e r ++; document . getElementById ( c o u n t e r ) . innerHTML=c o u n t e r ; startComet ( ) ; } } f u n c t i o n startComet ( ) { myRequest = CreateXmlHttpReq ( myHandler ) ; myRequest . open ( GET , h t t p : / / s e r v e r : 8 0 8 0 / echo , t r u e ) ; myRequest . send ( ) ; }
36 37 38 39 40 41
</ s c r i p t> </ head> <body onLoad= s t a r t C o m e t ( ) > <div id= c o u n t e r > 0 </ div> </ body> </ html>
Evaluation
Figure 2: Test local to Linux server, burst size 106 The tests were done on: server Intel R CoreTM i7 CPU 920 @ 2.67GHz Quad-core machine with 8GB of memory, running linux kernel 3.4.3 client AMD Athlon(tm) 64 x2 Dual-Core Processor TK-55 machine with 3GB of memory, running Windows 7 professional. 4
connected through a 1Gbps link. Figure 1 and 3 show the results of the test running on Windows remote machine with a burst size respectively of 106 and 107 . Figure 2 and 4 depict the corresponding results local to Linux server. Its possible to see that Opera [2] is the browser that reacts faster to asynchronous solicitation, both on Windows remote machine and on Linux server. Local to the server shares this primacy with Midori [3], a minimal browser for linux that aims to be lightweight and fast. Mozilla Firefox [4], Apple Safari [5], Microsoft Internet Explorer [6] and Konqueror [7] follow. Concerning Google Chrome [8] there is a strange anomaly in the test on Windows remote machine: it exibit a really slow behaviour. This is not notable in the test on Linux server, where Google Chrome show better performance than Mozilla Firefox. I didnt fully understand the reason of this strange behaviour. Looks like an Asynchronous parameter has to be set to true somewhere, but all the attempts didnt work.
The reasons why Opera is faster can be manifold. Someone on a forum said Opera is faster because they skip stronger privacy, but I dont think this is the reason. A step towards the anwser could be the fact that Opera 9 introduced a new feature called Server-Sent Events [9]. Using Server-Sent Events a developer can push DOM (Document Object Model) events continously from the web server to the visitors browser, eliminating the need for continuous polling, and this is exactly what Comet model does.
References
[1] Grizzly, http://grizzly.java.net [2] Opera, http://www.opera.com [3] Midori, http://twotoasts.de/index.php/midori [4] Mozilla Firefox, http://www.mozilla.org/it/firefox [5] Apple Safari, http://www.apple.com/it/safari [6] Microsoft Internet Explorer, internet-explorer http://windows.microsoft.com/it-IT/
[7] Konqueror, http://www.konqueror.org [8] Google Chrome, https://www.google.com/chrome [9] http://my.opera.com/WebApplications/blog/show.dml/438711 [10] Dave Crane, Phil McCarthy. Comet and Reverse Ajax: The NextGeneration Ajax 2.0. http://books.google.it/books?id=HK7ebSVtyKUC