Asp. Net implements Http persistent connection push, and asp.net implements http
Let's talk about how to help a friend develop smart home and build a cloud platform. The main function of a mobile phone is to forward the commands of a mobile client and an intelligent network in an external LAN environment.
Currently, a stable Socket version is available, but considering that future expansion and performance indicators need to be changed to the form of Http persistent connections, this is indeed a very tricky solution.
The concept of Http persistent connection is popularized below. The so-called Http persistent connection does not refer to the establishment of a connection client and server like Socket to transmit data back and forth. Http persistent connection means that the Http request sent from the client to the server does not immediately receive a response from the server. However, when certain conditions are met, the server "actively" returns the data to the client, at this time, an Http request is complete. In actual applications, a persistent connection is often established after the client ends a persistent connection, that is, the client always maintains an open downstream Http channel to the server.
Socket communication requires heartbeat commands in addition to its own protocol to ensure the connection status between the client and the server. I will not go into these articles, but mainly talk about the small frame of persistent connections.
Code is our best partner. Let's talk about this simple thing with the code below.
Many asynchronous features are added to Asp. Net4.0. IHttpAsyncHandler and IAsyncResult can effectively meet the requirements of this article. First, we define a class to implement the IAsyncResult interface.
Using System; using System. collections. generic; using System. linq; using System. web; using log4net; namespace SM. BIZKeepAliveHttp {// <summary> // an asynchronous session, which will be temporarily cached // </summary> public class HKAsyncRequest: IAsyncResult {private static readonly ILog logger = LogManager. getLogger (typeof (HKAsyncRequest); public HKAsyncRequest (HttpContext context, AsyncCallback cb, object extraData) {this. context = c Ontext; this. callBack = cb; this. extraData = extraData;} public HttpContext Context {get; set;} public object ExtraData {get; set;} public AsyncCallback CallBack {get; set;} public bool IsCompleted {get; set;} public object AsyncState {get; set;} public System. threading. waitHandle AsyncWaitHandle {get; set;} public bool CompletedSynchronously {get {return false ;}} public void Send (String response) {if (String. isNullOrEmpty (response) return; try {this. context. response. contentType = "text/plain"; this. context. response. write (response); if (this. callBack! = Null) {this. callBack (this) ;}} catch (Exception ex) {logger. error ("Error output to client:" + ex. message) ;}finally {IsCompleted = true ;}} public void Send (byte [] B, int offset, int length) {string str = Func. byteArrayToHexString (B); this. send (str );}}}
This class is not difficult. It mainly stores HttpContext, AsyncCallBack, and ExtraData that are passed in externally. HttpContext is used to write a Response to Response, and AsyncCallBack is used to end the current Http persistent connection request, I didn't use ExtraData for what I should do. Note that the CompletedSynchronously attribute in this class should return false, otherwise the client will not receive the data. In addition, do not return null for each attribute. Otherwise, a null pointer error will be reported when Response is written.
Next we will look at the implementation of another interface. Create a general processing program (. ashx) file in the project. Implement the IAsyncHandler interface:
Using System; using System. collections. generic; using System. linq; using System. web; using log4net; using Newtonsoft. json. linq; namespace SM. BIZKeepAliveHttp {public class Data: IHttpAsyncHandler {public static readonly string DATAFIELD = "data"; private static readonly ILog logger = LogManager. getLogger (typeof (Data); public IAsyncResult BeginProcessRequest (HttpContext context, AsyncCallback cb, object extraData) {context. response. cache. setCacheability (HttpCacheability. noCache); string value = context. request. params. get (DATAFIELD); // SessionId is passed here, not data, data is not duplicated Parse // use sessionId to find the corresponding session in the cache, and fill in AsyncResult HKAsyncRequest result = new HKAsyncRequest (context, cb, extraData); string error = null; if (String. isNullOrEmpty (value) {error = "500 SessionId is null"; context. response. status Code = 500; logger. error (error); result. send (error); return result;} List <AliveClient> acs = AsyncManager. sessions. findAll (x => x. sessionId. equals (value); if (acs = null | acs. count = 0) {error = "404 SessionId:" + value + "has no connection. "; context. response. status Code = 404; logger. debug (error); result. send (error); return result;} AliveClient ac = acs. first (); ac. result = result; // execute the command CommondFactory. executeCommond (ac); return result;} public void EndProcessRequest (IAsyncResult result) {} public void ProcessRequest (HttpContext context) {} public bool IsReusable {get {return false ;}}}}
Only one method is implemented in this class, that is, BeginProcessRequest. Other methods do not need to write any code. This method is mainly used to create an IAsyncResult instance and save it, so that the server can return the data to the client if it has data or meets specific conditions. So I created a static List cache in the code to save these IAsyncResult implementations. Of course, this is the core of Asp. Net to implement Http persistent connections.
I will not talk about anything else. You can look at the source code. When you look at the code, you will find that I have actually created two. the ashx file, which is related to the logic of my project, because the Protocol requires the client to send a piece of data and the server will immediately respond, so I use a traditional ashx to respond, the traditional ashx (connection. ashx) first analyzes the data and saves the analyzed data model. At the same time, it gives the client a SessionId. After the client receives a response, it uses this SessionId to initiate a persistent connection request. The server no longer analyzes the data repeatedly, but instead extracts and uses the previous data from the cache, for debugging convenience, I have killed this SessionId. At the same time, I used Quartz. Net to create two tasks. One CleanJob. cs is actually used as a cleanup task, which regularly clears invalid or completed requests in the cache and runs once every 5 minutes. Another task is HeartJob. cs, which is mainly used to simulate the logic of server push and runs once every 30 seconds.
Quartz. Net is used because I personally think that the method of directly starting BackgroundWorker in Asp.net is not very good, or the thread model of the scheduling engine is more reliable. The specific code for starting the scheduling engine is in Global. asax.
The attachment contains the code that I strip out, And the deleted business part is only used for testing. The test interface is index. aspx. In the text box, click. After receiving the server response, the alert window is displayed every 30 seconds after receiving the server response. The key here is that the client js Code immediately establishes a persistent connection after receiving a long connection feedback, which is the key.
Source code
Does http persistent connection support Android push?
I think this is the ajax round-robin method, so it cannot be said that the server pushes messages to a user, because http is based on the request response. This can also be used if mobile phone versions are developed, but the efficiency is not high. If android is used, some push technologies are already open-source and can be directly used, this function can be fully implemented. When I tried to develop android, I used the androidpn push technology to implement chat and server push.
How does winform maintain a persistent connection with aspnet?
Activate thread processing and add a heartbeat judgment mechanism, that is, let your winform send a piece of data to your server at intervals to prove that the connection is still in progress, if the server does not receive the response after this time, it is deemed that it has been disconnected, killed the thread, and called Application. close () ends winform. If you feel this is too insecure, you can re-send or even trigger the heartbeat information again when the timeout occurs. If the heartbeat information is not received from the server, the connection is closed, perform the same steps