Client-server continuous synchronous parsing (polling, Comet, websocket)

Source: Internet
Author: User

In B/S model Web applications, the client often needs to maintain continuous updates with the server. Such applications that require high timeliness include stock price queries, real-time commodity prices, automatically updated Twitter timeline, and browser-based chat systems (such as Gtalk. Due to the rise of Ajax technology in recent years, there have also been many implementation methods. This article will describe these methods and demonstrate them with jquery + tornado. It should be noted that if you do not know Tornado, the tornado code is very clear and easy to understand, tornado is selected because it is a non-blocking (non-blocking Io) asynchronous framework (Version 2.0 is used in this article ).

 

Before you start, to give everyone a clear understanding, first list the content to be discussed in this article. This article will be divided into the following parts:

  1. Polling)
  2. Comet: Based on the "server push" Technology for persistent server connections. There are two types:
    1. Based on Ajax and IFRAMEStreaming Mode.
    2. Ajax-basedLong-polling.
  3. Websocket

 

 

Old round robin

Round Robin is the simplest and easiest way to implement. queries are sent to the server at intervals, and related events are triggered after an update. For the front-end, use the setinterval of js to regularly send requests to the server in Ajax or jsonp mode.

var polling = function(){
$.post('/polling', function(data, textStatus){
$("p").append(data+"<br>");
});
};
interval = setInterval(polling, 1000);

 

At the backend, we generate numbers randomly and return them. In practical applications, you can access the cache or obtain content from the database.

import random
import tornado.web

class PollingHandler(tornado.web.RequestHandler):
def post(self):
num = random.randint(1, 100)
self.write(str(num))

 

As you can see, the efficiency of polling is very low. On the one hand, the server side does not always have data updates, so each query may not always have updates, which is inefficient. On the other hand, when the number of clients initiating a request increases, the number of requests accepted by the server increases significantly, which increases the pressure on the server.

  Comet: server push technology based on HTTP persistent connections

Some people may be dizzy when they see this title. In fact, the principle is relatively simple. Comet-based technologies are mainly divided into stream mode and long-polling mode.
 

First of all, let's look at the word Comet. Many places will say that it means a comet. As the name suggests, a comet has a long tail, which indicates that the client initiates a long connection request. That is, the user suspends the request and waits for the server to return data, during which the connection will not be closed. The difference between the stream mode and the long polling mode is that for the stream mode, when the client initiates a connection, the connection will not be disconnected, but is controlled by the server. When there is an update on the server side, the client refreshes the data and updates the data. For long polling, when the server side returns an update, the client first disconnects, processes it, And then initiates a new connection.
 

Some may ask why the stream and long-polling methods are required? It is because there are many restrictions on the stream mode. If Ajax is used, you need to determine the readystate of XMLHttpRequest, that is, when readystate = 3 (data is still being transmitted). The client can read data without closing the connection. This is also the problem. When the readystate of IE is 3, the data returned by the server cannot be read. Therefore, ie currently does not support streaming Ajax, while long polling is a common Ajax request, therefore, there is no browser compatibility problem. In addition, because the streaming method is used, the control is on the server side, and there is no data from the client to the server during the long connection period, therefore, the client data cannot be used for instant adaptation (such as checking cookies), but the long polling method can be determined after each disconnection. Therefore, long polling is a mainstream practice (such as FB and plurk ).

 

Next, we will demonstrate streaming and long-polling.

 

Streaming Mode

It can be seen that the connection will not be closed for each data transmission, and the connection will only be closed when a communication error occurs or the connection is rebuilt (Some firewalls are often set to discard too long connections, you can set a timeout time on the server to notify the client to re-establish the connection and close the original connection after the timeout ).

The first common method of stream mode is to useAjax stream mode(As mentioned earlier, this method mainly determines the situation when readystate = 3, so it cannot be applied to IE ).
 

The server code is as follows:

Class streaminghandler (tornado. Web. requesthandler ):
'''Use the asynchronus decorator to make the POST method non-blocking '''
@ Tornado. Web. asynchronous
Def post (Self ):
Self. get_data (callback = self. on_finish)

Def get_data (self, callback ):
If self. Request. Connection. Stream. Closed ():
Return

Num = random. randint (1,100) # generate a random number
Callback (Num) # Call the callback function

Def on_finish (self, data ):
Self. Write ("server says: % d" % data)
Self. Flush ()

Tornado. ioloop. ioloop. instance (). add_timeout (
Time. Time () + 3,
Lambda: Self. get_data (callback = self. on_finish)
)

On the server side, a random number is still generated. To continuously output data, the callback function will be delayed for 3 seconds and then the get_data method will be called. Note that time. Sleep () cannot be used. Because tornado is single-threaded, the sleep method blocks the main thread. Therefore, call the add_timeout method of ioloop (parameter 0: Execution timestamp, parameter 1: callback function ). As a result, the server generates a random number, which is generated after a delay of 3 seconds.
 

The front-end JS is:

Try {
VaR request = new XMLHttpRequest ();
} Catch (e ){
Alert ("browser doesn't support window. XMLHttpRequest ");
}

VaR Pos = 0;
Request. onreadystatechange = function (){
If (request. readystate = 3) {// process in interactive mode
VaR DATA = request. responsetext;
$ ("P"). append (data. substring (POS) + "<br> ");
Pos = data. length;
}
};
Request. Open ("Post", "/streaming", true );
Request. Send (null );

For tornado, calling the flush method will send all the previously written data to the client, that is, the response data is accumulated, so in the JS script, we use the POs variable as the cursor to store the end position of each flush data.

 

Another common method isUse the streaming mode of IFRAMEThis is also a common practice in the past. First, we place an IFRAME in the page, and its SRC is set to a persistent connection request address. The code on the server is basically the same, but the output format is changed to HTML, which is used to output the inline JavaScript of a row. Since the output is executed, the stored cursor (POS) process is missing. The server code is as follows:

Class iframestreaminghandler (tornado. Web. requesthandler ):
@ Tornado. Web. asynchronous
Def get (Self ):
Self. get_data (callback = self. on_finish)

Def get_data (self, callback ):
If self. Request. Connection. Stream. Closed ():
Return

Num = random. randint (1,100)
Callback (Num)

Def on_finish (self, data ):
Self. Write ("<SCRIPT> parent. add_content ('server says: % d <br/> '); </SCRIPT>" % data)
# Execute the output immediately and call the parent window JS function add_content
Self. Flush ()

Tornado. ioloop. ioloop. instance (). add_timeout (
Time. Time () + 3,
Lambda: Self. get_data (callback = self. on_finish)
)

On the client side, we only need to define the add_content function:

var add_content = function(str){
$("p").append(str);
};

From this we can see that the IFRAME streaming method solves the browser compatibility problem. However, because the traditional Web Server occupies a connection thread every time it connects to the server, the threads in the thread pool will eventually use up as the client grows to connect to the server. Therefore, comet persistent connections can only be used for non-blocking asynchronous Web servers. This is why tornado is selected.

One problem with IFRAME is that the browser is always loading.

 

Long-polling

Long polling is currently the most common method. The difference between this method and the stream mode is that the server suspends after receiving the request. When there is an update, the server returns the connection to be disconnected, and then the client initiates a new connection. The server-side code is much simpler, similar to the preceding task:

Class longpollinghandler (tornado. Web. requesthandler ):
@ Tornado. Web. asynchronous
Def post (Self ):
Self. get_data (callback = self. on_finish)

Def get_data (self, callback ):
If self. Request. Connection. Stream. Closed ():
Return

Num = random. randint (1,100)
Tornado. ioloop. ioloop. instance (). add_timeout (
Time. Time () + 3,
Lambda: callback (Num)
) # Call the callback function at an interval of 3 seconds

Def on_finish (self, data ):
Self. Write ("server says: % d" % data)
Self. Finish () # Use the finish method to disconnect

In browser, we encapsulate it into an Updater object:

var updater = {
poll: function(){
$.ajax({url: "/longpolling",
type: "POST",
dataType: "text",
success: updater.onSuccess,
error: updater.onError});
},
onSuccess: function(data, dataStatus){
try{
$("p").append(data+"<br>");
}
catch(e){
updater.onError();
return;
}
interval = window.setTimeout(updater.poll, 0);
},
onError: function(){
console.log("Poll error;");
}
};

To enable long polling, you only need to call

updater.poll();

As you can see, long polling is more efficient than normal polling (data is returned only when data is updated), reducing unnecessary bandwidth waste. At the same time, long polling improves the streaming method to identify and update the browser.

Websocket: Future Direction

No matter what the comet method is, the above is actually only one-way communication, until the emergence of websocket, is the real full duplex communication between B/S. However, the websocket protocol is still under development. Currently, chrome and safri browsers support websocket by default, while ff4 and opera disable websocket by default for security considerations, while IE does not support websocket (including 9 ), currently, the latest websocket protocol is draft 76 ". If you are interested, follow http://dev.w3.org/html5/websockets /.
 

After each websocket request is initiated, the B/S side performs a handshake to implement communication. The communication principle is the same as that of the socket. Currently, tornado2.0 also implements the "Draft No. 76" of websocket ". For more information, see the documentation. We still send a bunch of random numbers after the communication is opened, which is only used for demonstration.

import tornado.websocket

class WebSocketHandler(tornado.websocket.WebSocketHandler):
def open(self):
for i in xrange(10):
num = random.randint(1, 100)
self.write_message(str(num))

def on_message(self, message):
logging.info("getting message %s", message)
self.write_message("You say:" + message)

The client code is also simple and intuitive:

var wsUpdater = {
socket: null,
start: function(){
if ("WebSocket" in window) {
wsUpdater.socket = new WebSocket("ws://localhost:8889/websocket");
}
else {
wsUpdater.socket = new MozWebSocket("ws://localhost:8889/websocket");
}
wsUpdater.socket.onmessage = function(event) {
$("p").append(event.data+"<br>");
};
}
};
wsUpdater.start();

 

Summary: This article introduces and demonstrates the method of continuous synchronization between browser and server. In actual production, there are some frameworks. Including pushlet of Java and socket. Io of nodejs. For details, refer to them.

References:

  1. Browser and server adopt synchronous routing (polling, Comet, long polling, websocket) (may have to go through the wall)
  2. Comet: server push technology based on HTTP persistent connections

This article is from the sun-like blog: several methods of continuous synchronization between browser and server (jquery + tornado demonstration)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.