Use. NET to implement Ajax persistent connections

Source: Internet
Author: User
Document directory
  • Timeout caused by no event
  • Define Sending target
  • Reliable Message Queue
  • Summary
  • Monitor Model
  • Mutex Model
  • Simple Example
  • Experience
  • Summary

By http://www.cnblogs.com/cathsfz/

 

Ajax persistent connections, or some people refer to Comet, are used to connect to the server in XMLHttpRequest mode. After the connection, the server does not instantly write the corresponding data and return the data. The server will keep the connection and wait for an event to notify the client. After the event occurs, the data will be written to the response immediately. At this time, the client will receive the event notification in a fairly "real-time" manner. For specific communication models, refer to this article :《Comet: server push technology based on HTTP persistent connectionsAnd I will not repeat it again.

We will discuss how to use. NET to implement this model. First, we can think of a Web Service, which can be ASP. NET Web Service, WCF Web Service, and ASP. net ajax Library. Here, for the sake of simplicity, We will select an example of ASP. NET Web Service that you are more familiar. Then, we will write down the following two function signatures:

Public void Send (Message message );
Public Message Wait ();

The Send function is used to Send a Message object, while the Wait function is used to Wait for a Message object. Then let's discuss some details.

Timeout caused by no event

First, it will not work if you keep the connection for a long time. This is not a problem for servers and clients, but we should always remember that there may be various gateways and proxies with weird configurations, which may have various timeout rules, therefore, it is recommended that Comet be designed for regular reconnection. Generally, if no event occurs within 30 seconds, the server should notify the client that no event has occurred, end the request, and start a new request to continue waiting.

Can the above function signature be used to return an event-free message? This is obviously acceptable. We can choose to return null to indicate no event, or return a EmptyMessage constant, depending on whether we use class or struct to define Message. (Even we can create a Message derived class named NoMessageMessage To Do This .)

Define Sending target

The above function signature can indeed be used for sending and receiving messages, but it does not indicate who to send messages. It may be said that the sender can be defined by an attribute in the Message class. However, the Wait () method does not indicate who the receiver is, and the server still does not know which messages should be received by you.

Therefore, we introduce the concept of Channel, which is identified by its name. The same Channel must have the same name. When sending and receiving data, specify the Channel to which the data is sent by using the name. This solves the problem. Modify the function signature as follows:

Public void Send (string channelName, Message message );
Public Message Wait (string channelName );

Reliable Message Queue

Imagine a possible situation where the server sends a message to you. If you fail to receive the message, the server determines that the message is successfully sent and the message is deleted from the queue, then the message is lost permanently. Some people may emphasize how reliable TCP is. If a message sent by the server has a problem at the TCP level, it will certainly cause a Socket-level Exception, which is bubbling up, the server can intercept the message, so that the message fails to be sent, and the first message of the queue is not deleted first. But don't forget that there may be a proxy in the middle. If the proxy successfully removes the message, but the proxy fails to send the message to the client, the server may not have an exception.

Therefore, we need to develop a policy to ensure that downstream messages are always sent to the client. Here, we chose to introduce an ACK-by-one mechanism to confirm message receipt. That is to say, the message sent from the server to the client carries a serial number. After the client receives the message, it sends the serial number back to the server, and it has been confirmed that it has received the message. At this time, the function signature is changed as follows:

Public int Send (string channelName, Message message );
Public Message Wait (string channelName, int sequence );

In the Message we receive using Wait (), there should be a Sequence attribute, marking its serial number. Then, when we execute the next Wait () operation, we will pass the value of the serial number plus 1 back through the sequence parameter to let the server know that the number of the next message we expect is this. For example, if we receive a Message whose Sequence attribute is 836, it will be sent to server 837 when Wait () is called next time. At this time, the server should keep the Message No. 836 at the beginning of the pair. If the client continues to request Message No. 836, it proves that it did not receive the Message last time, and this time it still sends the Message No. 836 to it; if the client requests Message No. 837 to prove that it has successfully received message No. 836, this time it will send message No. 837 to it.

If not, what should I do? This means that this is a wrong request, or even an attack request, because such a request should not appear normally, the server may consider throwing an insignificant Exception (do not tell the attacker that he is under attack), or even directly sending a 400 (bad request) response code.

Similar to Wait (), Send () can also be added to the ACK mechanism. You only need to change the return type from void to int. This value is used to transmit message numbers, the implementation method is the same as that of Wait (), but Send () is the queue in which the client saves the messages to be sent.

Summary

So far. Our Web Service is ready. Is this all written? Only the signature does not have a function body? Yes, the complex work is left for the model. Here, the Web Service is equivalent to a view, which is used to expose the model interface.

In the next article, we will begin to discuss how to implement the message transmission mechanism on the server.

 

In the previous article, we talked about how to design an ASP. NET Web Service to process persistent connection requests. Many people have asked this question. How can I hold the request and keep it open for 30 seconds? This is actually very simple. Just Sleep:

Thread. Sleep (30*1000 );

However, the problem is that we don't have to wait 30 seconds to check whether an event needs to be returned, but that an event can be returned at any time within these 30 seconds. Therefore, we need a mechanism to check whether an event has occurred while waiting.

Monitor Model

In. NET, the most familiar Thread Synchronization Model should be the Monitor model. Have you heard of it? It is the lock keyword of C #. In fact, it is compiled into a pair of Monitor. Enter () and Monitor. Exit ().

By using the lock command, we can create a critical section for an object. When the code is executed to the entry of the critical section, the lock of the object must be obtained before execution, and the lock can be released at the exit of the critical section. However, this model is not suitable for solving our problem, because we need to wait for an event. If we use lock to wait, we need to lock the object outside the Web Service first, then, when the event is triggered, the Web Service is unlocked and enters the critical area smoothly.

In fact, there is a better choice for this type of blocking, that is, Mutex.

Mutex Model

Mutex is the abbreviation of mutual exclusive. How does Mutex work? This is a bit like a bank queuing call system. All the waiting persons are waiting in the lobby to wait (wait). When a service window is idle, it will send a signal (signal) to notify the next person waiting for the service. In short, all threads that execute wait commands are waiting, and each signal can end a thread and wait for execution to continue.

In. NET, the wait and signal operations correspond to the Mutex. WaitOne () and Mutex. ReleaseMutex () methods respectively. We can let the Web Service thread use Mutex. WaitOne () to enter the waiting state, and use Mutex. ReleaseMutex () to notify the Web Service thread when an event occurs. Because it must be in Mutex. after ReleaseMutex () occurs, Mutex. waitOne () can continue to execute, so if it can be executed, it proves that there must be an event and Mutex is called. releaseMutext (). At this time, you can read the event message with confidence.

Simple Example

After selecting to use the Mutex model, we will compile a simple example. First, we need to define a Mutex In the WebService derived class and a message string.

Mutex mutex = new Mutex ();
String message;

Then, we define two webmethods. In order to simplify the problem, we chose the two function signatures mentioned in the previous article, that is, we can only send and receive functions in one Web Service, without the concept of sending targets, there is no timeout concept and no reliability design. At the same time, we replace the Message type with a normal string for testing.

First, write the function for sending messages:

Public void Send (string message ){
This. message = message;
This. mutex. ReleaseMutex ();
}

In this sending function, we first put the message into the global variable in the class, and then let the global Mutex class release a signal. At this time, if a thread is waiting, it can be executed immediately. If no thread is waiting at this time, the next wait thread will be able to continue to execute to the blocked place without being blocked.

Now let's compile the function for receiving messages:

Public string Wait (){
This. mutex. WaitOne ();
Return this. message;
}

The receiving function enters the wait Status at the beginning. After signal is obtained, the global message is returned to the client.

Experience

Finally, we can test our code through the Web test interface supported by ASP. NET Web Service itself. We open two browser windows, one for sending () and the other for Wait. Then we can test it as follows:

  1. Run Send ("Hello") and Wait (). Now you can see "Hello ".
  2. First, run Wait () to Wait for the response. Then, run Send ("Hello "). Then you can see that the Wait () section returns "Hello.
  3. Run the command in the following order: Send ("Hello"); Wait (); Send ("World"); Wait ();
  4. Run the following command: Send ("Hello"); Send ("World"); Wait ();
  5. Run the command in the following order: Wait (); Send ("Hello"); Send ("World ");
  6. Run the command in the following order: Wait (); Send ("Hello"); Wait (); Send ("World ");

You will find some strange results: "World" and "World" are returned for the 3rd tests ". The Wait () thread that first executes does not necessarily return "Hello" for the 5th tests. In some cases, the latter is not a problem. In particular, in persistent connections, the second Wait () thread is waiting, so we can ignore it. The former is because there is no message queue. We only have one message window, so we can only cache the last message. We will solve this problem in the next article.

Summary

In this article, we see the differences between different thread synchronization models. The lock of the Monitor Model is essentially a Semaphore, that is, a Mutex that cannot be consecutive signal. After a signal is sent, it must be received by a wait before the next signal can be performed. At the same time, Semaphore also limits that signal and wait must be executed in pairs in the same thread, while Mutex does not. Although. NET is optimized for the Monitor model, we only need to use the Mutex model to solve our needs.

Then, we wrote a small function for sending and receiving consumers, implementing the blocking Web Service we wanted. At the same time, we also saw the problem caused by no message queue, so we are sure to create a message queue.

Related Article

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.