Motivation: My friend told me that he implemented a message reminder mechanism in his company. I asked him how he did it. He said that he implemented it by calling ajax regularly. I told him that when I used web qq, I didn't see the system checking for messages regularly, but strangely, as soon as there was a message, it could be delivered to you at the fastest speed (pushed from the server to the client, I don't know if there was any semantic error, please give me your advice). Today, over the weekend, I had time to think about how to simply implement this feature, so google found a five-minute video, quickly learned the principle and implemented it with asp.net (because that video was implemented in php).
Attach the original video address: http://www.screenr.com/SNH
Because the principle is simple, so paste code directly.
ReqHandler.ashx
using System; using System.IO; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Web; namespace SimpleAjaxLongPolling { /// <summary> /// Summary of ReqHandler /// </summary> public class ReqHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; string baseDir = "~/Data/"; string fileName = "datasrc.txt"; string filePath = context.Server.MapPath(baseDir + fileName); /* * Timeout counter */ byte timeoutCount = 0; /* * Get the last modification time of the file */ long otimestamp = File.GetLastWriteTime(filePath).Ticks; long ctimestamp = File.GetLastWriteTime(filePath).Ticks; /* * Get the last modification time of the file in the last connection feedback sent to the client to determine * Has the file been modified when the new connection comes in, if this parameter is not empty and not * 0 (initial value is 0), which indicates that there has been connection feedback to the customer, and this value is used. * To be the object of comparison with or without modification. */ var reqTimeStamp = context.Request.QueryString["ts"]; if (!string.IsNullOrEmpty(reqTimeStamp) && !reqTimeStamp.Equals("0")) { otimestamp = Convert.ToInt64(reqTimeStamp); } /* * Core. If the file has not been modified (that is, new content) since the last connection, and has not exceeded * When waiting, the timeout counter increases. * The condition for a loop to jump out is that the file has been modified (with new content) or timed out. */ while (ctimestamp <= otimestamp && timeoutCount < 30) { Thread.Sleep(1000); ++timeoutCount; ctimestamp = File.GetLastWriteTime(filePath).Ticks; } var outputMsg = String.Empty; // Operation after loop jump if (timeoutCount < 30) { /* * If it does not time out, then there is something new. */ var lines = File.ReadAllLines(filePath); if (lines.Length > 0) { outputMsg = lines[0]; } } var output = string.Format("{{'msg':'{0}', 'timestamp':'{1}'}}", outputMsg, ctimestamp); context.Response.Write(output); } public bool IsReusable { get { return false; } } } }
GetMsg.aspx
<form id="form1" runat="server"> <div id="msg_zone"> <ul id="msg_list"> <li>Waiting for messages...</li> </ul> </div> </form> <script type="text/javascript"> var $msgFmtStr = '<li>%1</li>'; var $timestamp = 0; var $timer = null; $(document).ready(function () { getMsgs(); }); function getMsgs() { $.ajax({ type: 'GET', async: true, cache: false, url: 'ReqHandler.ashx', data:{ts:$timestamp}, success: function (data) { var $json = eval('(' + data + ')'); if ($json['msg'] != '') { $('ul#msg_list').append($msgFmtStr.replace('%1', $json['msg'])); } $timestamp = $json['timestamp']; getMsgs(); }, error: function (XMLHttpRequest, textState, error) { $('ul#msg_list').append($msgFmtStr.replace('%1', 'Error:(' + textState + ', ' + error + ')')); setTimeout("getMsgs()", 5000); } }); } </script>
Attach demo download address:
http://pan.baidu.com/share/link?shareid=541364&uk=657243248
Supplement:
In view of some gardeners questioning my code, I add the following content, welcome you to continue to participate in exchanges, after all, it is the first time to know the long connection, do not know whether they know it or not, I hope to get bulls'advice.
First of all, see the picture:
Each call initiates a connection, which is maintained because the server is not responding, as shown in the red box. The figure shows that the connection is maintained for 30 seconds (because the backend uses 30 seconds as the connection timeout). Within 30 seconds, the connection will be blocked all the time, but the operation of the client will not be blocked until it returns, releases the connection, and then executes the next connection, that is to say, calls getMsgs() again. Note, however, that getMsgs() is not always called because it is conditional.
First: $(document).ready();
Secondly, if the connection initiated is responded and the Status is OK, it will be called immediately, and if an error occurs, the function will be called again after 10 seconds.
So there will be 100% CPU occupation without client, and the server will not occupy too much CPU because of Sleep.
Please provide better solutions, learn together, ths!
Reprinted at: https://www.cnblogs.com/syblogs/archive/2013/05/18/3085575.html