Long connection based on HTTP is a technology to realize “server push” through long polling. It makes up for the deficiency of simple HTTP request response mode, and greatly enhances the real-time and interactive nature of the program.
First, what is long connection, long polling?
In plain English, the client keeps sending requests to the server to get the latest data. Here “stop” actually has a stop, but our eyes can not tell whether to stop, it is just a quick stop and immediately began to connect.
2. Application scenarios of long connection and long polling
Long links and long polling are commonly used in WebIM, ChatRoom and other web applications that require timely interaction. Its real cases are: WebQQ, Hi web page version, Facebook IM and so on.
If you are interested in server-side reverse Ajax, you can refer to this article DWR reverse Ajax server push way: www.cnblogs.com/hoojo/categ…
Three, advantages and disadvantages
** Polling: ** The client periodically sends Ajax requests to the server, which immediately returns a response and closes the connection. Advantages: Easy to write back-end programs. Disadvantages: Most requests are useless, wasting bandwidth and server resources. Example: Suitable for small applications.
** Long polling: ** The client sends an Ajax request to the server. The server receives the request and holds the connection until it receives a new message and closes the connection. The client processes the response and then sends a new request to the server. Advantages: Less frequent requests without messages and less resource consumption. Disadvantages: server hold connection will consume resources, return data sequence is not guaranteed, difficult to manage and maintain. Examples: WebQQ, Hi web edition, Facebook IM.
** Long connection: ** Embed a hidden IFrame in the page, set the SRC attribute of this hidden IFrame to a request for a long connection or use XHR request, the server can continuously input data to the client. Advantages: Instant message arrival, do not send useless request; It is also relatively easy to manage. Disadvantages: Server maintenance of a long connection can add overhead. Example: Gmail Chat
* * Flash Socket: ** Embedded in the page a Flash program using the Socket class JavaScript by calling the Flash program provided by the Socket interface to communicate with the server side Socket interface, JavaScript after receiving the information sent by the server side control page display. Advantages: real instant communication, rather than pseudo instant. Disadvantages: Flash plug-in must be installed on the client; If the protocol is not HTTP, the firewall cannot be automatically traversed. Example: Online interactive games.
Four, implementation principle
The so-called long connection is to create and maintain a stable and reliable connection between the client and the server. In fact, it is a very old technology, but due to the slow development of browser technology, there is no good support for the implementation of this mechanism. So to achieve this effect, the client and server programs need to cooperate to complete. A common practice is to put an infinite loop in the server’s program to monitor changes in the data. When it finds new data, it immediately outputs it to the browser and disconnects. After the browser receives the data, it launches another request to proceed to the next cycle, which is often referred to as long-polling. As shown in the figure below, it usually consists of the following key processes:
- The process of polling is very simple. After the browser initiates a request, it enters a circular waiting state, and the HTTP is still connected because the server has not responded.
- Data push During the cycle, the server program monitors data changes. If it finds updates, it outputs the information to the browser, and then disconnects to complete the response process, realizing “server push”.
- Polling termination Polling may be terminated in the following three situations: 3.1. New Data Push When the server pushes information to the browser during the loop, it should actively terminate the application to disconnect the connection so that the browser can receive data in a timely manner. 3.2. The push cycle without new data cannot continue forever, so a maximum time limit should be set to avoid the WEB server Timeout. If there is no new information, the server should send the normal response to the browser and disconnect, which is also known as the “heartbeat” message. 3.3. Network Faults or Exceptions If a request times out or an error occurs due to a network fault, the browser will receive an error message. As soon as the browser receives the reply and processes it, it should re-initiate the request and start a new polling cycle.
5. Program design
1. Common polling in Ajax mode
Client code snippets
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"% > <! DOCTYPE HTML PUBLIC"- / / / / W3C DTD HTML 4.01 Transitional / / EN">
<html>
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="author" content="hoojo & http://hoojo.cnblogs.com">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<%@ include file="/tags/jquery-lib.jsp"%>
<script type="text/javascript">
$(function () {
window.setInterval(function () {
$.get("${pageContext.request.contextPath}/communication/user/ajax.mvc",
{"timed": new Date().getTime()},
function (data) {
$("#logs").append("[data: " + data + " ]<br/>");
});
}, 3000);
});
</script>
</head>
<body>
<div id="logs"></div>
</body>
</html>
Copy the code
The client implementation is the result of a common polling, which is relatively simple. Using setInterval to refresh continuously to retrieve server resources has the advantage of being simple and timely. The disadvantage is that links are mostly invalid and repetitive; The result of the response is not sequential (because it is asynchronous, subsequent requests are sent when the sent request does not return a result. If a subsequent request returns the result before the previous one, the result data will already be stale and invalid. Many requests are difficult to maintain and waste server and network resources.
Server-side code
@RequestMapping("/ajax") public void ajax(long timed, HttpServletResponse response) throws Exception { PrintWriter writer = response.getWriter(); Random rand = new Random(); // Query for data changes in an infinite loopwhile (true) { Thread.sleep(300); Int I = rate.nextint (100); int I = rate.nextint (100); // Generate a random number between 0 and 100if(I > 20 &&i < 56) {// If the random number is between 20 and 56, then the data is valid. Writer. print(request time, return time, time)"result: " + i + ", response time: " + responseTime + ", request time: " + timed + ", use time: " + (responseTime - timed));
break; // Break out of the loop and return data}elseThread.sleep(1300); }}}Copy the code
Server-side implementation, here on the simulation program monitoring data changes. The code above belongs to a method in Controller in SpringMVC, which is equivalent to a doPost/doGet method in a Servlet. If there is no program environment to accommodate the servlet, just copy the code from the method body into the servlet’s doGet/doPost.
1. Controllability of the server program to polling because polling is implemented in an infinite loop, the algorithm should ensure that the program has complete control over when to exit the loop, so as to avoid entering an infinite loop and depleting the server resources. **2. Choose a reasonable “heartbeat” frequency
** As you can see from Figure 1, long connections must be maintained by client requests, so it is critical to maintain a normal “heartbeat” between the client and the server. POLLING_LIFE should be shorter than the WEB server timeout, which is generally recommended to be between 10 and 20 seconds. **3. Influence of network factors
* * in practical application, make a response from the server, to the building of the next cycle, there is a time delay, the length of the delay time is influenced by many factors such as network transmission, during this period, the long connection in temporarily disconnected gap, if just have changed the data in this period of time, the server is unable to push immediately, so, In algorithm design, attention should be paid to the problem of data loss caused by delay. In long-connection applications, the server maintains a persistent connection with each client instance, which consumes a lot of server resources, especially in some large application systems. A large number of concurrent long connections may cause new requests to be blocked or even system crash. Therefore, Special attention should be paid to the optimization and improvement of the algorithm during the program design, and the load balancing and clustering technology of the server should also be considered when necessary.
Above is the result returned, as you can see that the first request is not necessarily the first result returned. Order is not guaranteed, resulting in dirty data or useless connection requests. Waste of resources on the server or network is visible.
2. Common polling in IFrame mode
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"% > <! DOCTYPE HTML PUBLIC"- / / / / W3C DTD HTML 4.01 Transitional / / EN">
<html>
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<%@ include file="/tags/jquery-lib.jsp"%>
<script type="text/javascript">
$(function () {
window.setInterval(function() {$("#logs").append("[data: " + $($("#frame").get(0).contentDocument).find("body").text() + " ]<br/>");
$("#frame").attr("src"."${pageContext.request.contextPath}/communication/user/ajax.mvc? timed="+ new Date().getTime()); // Delay 1 second to request window.setTimeout(function () {
window.frames["polling"].location.reload();
}, 1000);
}, 5000);
});
</script>
</head>
<body>
<iframe id="frame" name="polling" style="display: none;"></iframe>
<div id="logs"></div>
</body>
</html>
Copy the code
Here the client program is to use the hidden IFrame to the server side constantly pull data, the data after the iframe can be filled in the page. As with the ajax implementation, the only difference is that if a request does not return data in response, the next request will start and the previous request will be stopped. If you want your application to do the same as the Ajax request above, you can assign a separate IFrame to each request. Here is the result returned:
Red is the request that was stopped without successful return, and black is the request that successfully returned data.
3. Long connection iframe mode
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"% > <! DOCTYPE HTML PUBLIC"- / / / / W3C DTD HTML 4.01 Transitional / / EN">
<html>
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="author" content="hoojo & http://hoojo.cnblogs.com">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<%@ include file="/tags/jquery-lib.jsp"%>
<script type="text/javascript">
$(function () {
window.setInterval(function () {
var url = "${pageContext.request.contextPath}/communication/user/ajax.mvc? timed=" + new Date().getTime();
var $iframe = $('<iframe id="frame" name="polling" style="display: none;" src="' + url + '"></iframe>');
$("body").append($iframe);
$iframe.load(function() {$("#logs").append("[data: " + $($iframe.get(0).contentDocument).find("body").text() + " ]<br/>");
$iframe.remove();
});
}, 5000);
});
</script>
</head>
<body>
<div id="logs"></div>
</body>
</html>
Copy the code
Each request has its own independent iframe, and when that iframe gets the data in response, it pushes the data to the current page. Using this approach is similar to asynchronous ajax interaction, which is also not sequential, expensive, and always has a loading bar attached to the address bar or status bar (htmlFile is a solution, Google’s attackers have already done this, and there are lib libraries available online). But the client side is relatively simple to implement.
If you want to keep order, you can skip setInterval and put the method that creates the IFrame in the load event, that is, use recursion. The adjusted code snippet looks like this:
<script type="text/javascript">
$(function() {(function iframePolling() {
var url = "${pageContext.request.contextPath}/communication/user/ajax.mvc? timed=" + new Date().getTime();
var $iframe = $('<iframe id="frame" name="polling" style="display: none;" src="' + url + '"></iframe>');
$("body").append($iframe);
$iframe.load(function() {$("#logs").append("[data: " + $($iframe.get(0).contentDocument).find("body").text() + " ]<br/>");
$iframe.remove(); / / recursive iframePolling (); }); }) (); }); </script>Copy the code
This ensures the order of requests, but it does not deal with delayed errors or requests that do not return results for a long time. It waits until the request is returned before creating the next iframe request, always maintaining a connection to the server. Compared with the above polling, the disadvantage is that the message is not timely, but the order of requests is guaranteed.
4, Ajax to achieve long connection
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8" isELIgnored="false"% > <! DOCTYPE HTML PUBLIC"- / / / / W3C DTD HTML 4.01 Transitional / / EN">
<html>
<head>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<%@ include file="/tags/jquery-lib.jsp"%>
<script type="text/javascript">
$(function() {(function longPolling() {
$.ajax({
url: "${pageContext.request.contextPath}/communication/user/ajax.mvc",
data: {"timed": new Date().getTime()},
dataType: "text",
timeout: 5000,
error: function (XMLHttpRequest, textStatus, errorThrown) {
$("#state").append("[state: " + textStatus + ", error: " + errorThrown + " ]<br/>");
if (textStatus == "timeout") {// Request timeout longPolling(); // Other errors, such as network errors, etc.}else {
longPolling();
}
},
success: function (data, textStatus) {
$("#state").append("[state: " + textStatus + ", data: { " + data + "} ]<br/>");
if (textStatus == "success") {// The request succeeded longPolling(); }}}); }) (); }); </script> </head> <body>Copy the code
The above code is the only Ajax way to make a long connection, the main advantage is to always keep a connection to the server. If the current connection request is successful, the data is updated and a new connection continues to be created to maintain contact with the server. If the connection times out or an exception occurs, a new connection is created to continue the request. In this way, the server and network resources are greatly saved, the performance of the program is improved, and the sequence of the program is guaranteed.
Six, summarized
Modern browsers support the Cross-Origin Resource Share (CORS) specification, which allows XHR to perform cross-domain requests, so script-based and IFrame based technologies have become an outdated need.
The best way to implement and use Comet as a reverse Ajax is through the XMLHttpRequest object, which provides a real connection handle and error handling. Of course, you chose the Comet pattern of using an XMLHttpRequest object (a simple Ajax request that is suspended on the server side) via HTTP long polling, which is supported by all Ajax-enabled browsers.
Long connection technology based on HTTP is the ideal choice for real-time interactive application development in the pure browser environment. With the rapid development of browsers, HTML5 will provide better support and wider application for it. In HTML5, there is a Websocket that can be very friendly to complete the long connection of this technology, there are also related information on the Internet, here will not do too much introduction.