Reverse Ajax, part 2nd: WebSocket

Source: Internet
Author: User
Tags java se

Transferred from: http://kb.cnblogs.com/page/112616/

Objective

Today, users are looking for fast, dynamic applications that can be accessed through the web. This article series shows how to use reverse Ajax (Reverse Ajax) technology to develop event-driven Web applications. The 1th part of the series describes reverse Ajax, polling (polling), streaming (streaming), comet, and long polling (long polling). You've learned how Comet uses HTTP long polling, which is the best way to reliably reverse Ajax, because all of the existing browsers provide support.

In this article, we'll learn how to use WebSocket to implement reverse Ajax. Code examples are used to help explain WebSocket, Flashsocket, server-side constraints, request-scope (request-scoped) services, and pause long-lived requests, and so on, you can download these source code in this article.

  Pre-conditions

Ideally, to fully appreciate this article, you should have a good understanding of Javascrpit and Java. The example created in this article was built using Google Guice, a dependency injection framework written in Java. To read the text, you should be familiar with the concept of a dependency injection framework such as Guice, Spring, or Pico.

To run the examples in this article, you'll also need the latest version of Maven and JDK (see Resources).

WebSocket

The websocket that appears in HTML5 is a new inverse Ajax technology that is newer than comet, WebSocket enables bidirectional full-duplex communication channels, which are supported by many browsers (Firefox, Google Chrome, and Safari). The connection is opened by an HTTP request called the WebSocket handshake, which uses some special headers. The connection remains active, and you can use JavaScript to write and receive data, just as if you were using an original TCP socket interface.

The starting input for the WebSocket URL is ws://or wss://(on SSL).

The timeline in Figure 1 illustrates the communication using WebSocket. An HTTP handshake with a specific header is sent to the server side, and then the server or client can use JavaScript to access a socket (socket), which can be used to asynchronously receive data through the event handle.

Figure 1. Using WebSocket's Reverse Ajax

There is a websocket example in the source code that can be downloaded in this article, and you should see the output similar to listing 1 when you run the example. It explains how the client's events occur and how they are immediately displayed on the client. When the client sends some data, the server responds to the client's sending behavior.

Listing 1. Examples of websocket in JavaScript

[Client] WebSocket Connection opened
[Server] 1 events
[Event] ClientID =0
[Server] 1 events
[Event] At Fri June 1721:12:01 EDT 2011
[Server] 1 events
[Event] From 0:QQQ
[Server] 1 events
[Event] At Fri June 1721:12:05 EDT 2011
[Server] 1 events
[Event] From 0:VV

Typically, in JavaScript you will use WebSocket as described in Listing 2, if your browser supports it.

Listing 2. JavaScript Client Example

var ws = new WebSocket (' Ws://127.0.0.1:8080/async ');
Ws.onopen = function () {
Called when the connection is opened
};
Ws.onerror = function (e) {
Called when an error occurs, such as when the connection is broken
};
Ws.onclose = function () {
Called when the connection is closed
};
Ws.onmessage = function (msg) {
Called when a message is sent to the client on the server side
Msg.data contains the message
};
Here is how to send some data to the server side
Ws.send (' some data ');
Closing the Socket interface
Ws.close ();

The data sent and received can be of any type, and websocket can be seen as a TCP socket, so it depends on what type of data the client and server side know to send back and forth. The example here is to send a JSON string.

After the JavaScript WebSocket object is created, if you look at the HTTP request in the browser's console (or Firebug), you should see the WebSocket-specific header. Listing 3 shows an example.

Listing 3. HTTP request and corresponding header example

Request Url:ws://127.0.0.1:8080/async
Request Method:get
Status code:101 WebSocket Protocol handshake

Request Headers
Connection:upgrade
host:127.0.0.1:8080
origin:http://localhost:8080
Sec-websocket-key1:1 &1~ 33188YD]R8DP w75q
sec-websocket-key2:17; 229 *043m 8
Upgrade:websocket
(Key3): B4:bb:20:37:45:3f:bc:c7

Response Headers
Connection:upgrade
Sec-websocket-location:ws://127.0.0.1:8080/async
sec-websocket-origin:http://localhost:8080
Upgrade:websocket
(Challenge Response): ac:23:a5:7e:5d:e5:04:6a:b5:f8:cc:e7:ab:6d:1a:39

The WebSocket handshake uses all of these headers to validate and set a long-lived connection, and the WebSocket JavaScript object also contains two useful properties:

Ws.url: Returns the URL of the WebSocket server
Ws.readystate: Returns the value of the current connection state
1. Connecting = 0
2. OPEN = 1
3. CLOSED = 2

Server-side processing of websocket is slightly more complicated, and there is no Java specification that supports websocket in a standard way. To use the WebSocket functionality of a Web container (such as Tomcat or jetty), you need to tightly couple application code and container-specific libraries to access websocket functionality.

The example code in the WebSocket folder uses the jetty WebSocket API, because we are using the jetty container. Listing 4 shows the handler for the WebSocket. (the 3rd chapter of this series uses different backend WebSocket APIs.) )

Listing 4. WebSocket Handlers for jetty containers

Public final class Reverseajaxservlet extends Websocketservlet {
@Override
Protected WebSocket Dowebsocketconnect (httpservletrequest request,string protocol) {
return [...]
}
}

As far as jetty is concerned, there are several ways to deal with websocket handshake, the easier one is to subclass Jetty Websocketservlet and implement Dowebsocketconnect method. This method requires you to return an instance of the jetty WebSocket interface, and you must implement the interface and return some endpoint (endpoint) that represents the WebSocket connection. Listing 5 provides an example.

Listing 5. WebSocket implementation Examples

Class Endpoint implements WebSocket {
Outbound Outbound;
@Override
Publicvoid OnConnect (Outbound Outbound) {
This.outbound = outbound;
}
@Override
publicvoid onMessage (byte opcode, String data) {
Called when a message is received
That's the way you usually use it.
}
@Override
Publicvoid Onfragment (boolean more, byte opcode,byte[] data, int offset, int length) {
OnMessage is called when a piece of content is completed
It's not usually written in this way.
}
@Override
publicvoid onMessage (Byte opcode, byte[] data,int offset, int length) {
onMessage (opcode, new String (data, offset, length));
}
@Override
Publicvoid OnDisconnect () {
Outbound =null;
}
}

To send a message to the client, you write a message to outbound, as shown in Listing 6:

Listing 6. Send a message to the client

if (outbound! = null && outbound.isopen ()) {
Outbound.sendmessage (' Hello world! ');
}

To disconnect and close the WebSocket connection to the client, use Outbound.disconnect ().

WebSocket is a powerful way to implement no-delay bidirectional communication, and Firefox, Google Chrome, opera, and other modern browsers support this approach. According to the Jwebsocket website:

1. Chrome starts with a localized websocket from version 4.0.249.
2. Safari 5.x contains localized websocket.
3. Firefox 3.7a6 and 4.0b1+ contain localized websocket.
4. Opera starts with the 10.7.9.67, which includes localized websocket.

For more information on Jwebsocket, please refer to the Resources section.

  Advantages

The WebSocket is powerful, bidirectional, low latency, and easy to handle errors, and does not have many connections like Comet long polling or some of the drawbacks of comet streaming. Its API is also easy to use, without the need for additional layers to be used directly, while comet requires a good library to handle reconnection, timeouts, Ajax requests, confirmations, and the choice of different transports (Ajax long polling and Jsonp polling).

  Disadvantages

The disadvantages of WebSocket have these:

1. is a new specification from HTML5, which has not been supported by all browsers.

2. There is no requesting scope (request scope) because WebSocket is a TCP socket interface instead of an HTTP request, and the scoped request service, such as Hibernate sessioninviewfilter, is not easy to use. Hibernate is a persistence framework that provides a filter on the perimeter of the HTTP request. At the start of the request, it sets a context (including transaction and JDBC Connection) boundaries in the request thread, and at the end of the request, the filter destroys the context.

  Flashsocket

For browsers that do not support websocket, some libraries can be rolled back to Flashsocket (via the Flash's socket interface). These libraries usually provide the same official WebSocket API, but they are implemented by delegating calls to a hidden flash component that is contained in a Web site.

  Advantages

Flashsocket transparently provides websocket functionality, even on browsers that do not support HTML5 WebSocket.

  Disadvantages

Flashsocket has the following drawbacks:

1. It needs to install the Flash plugin (typically, all browsers will have the plugin).

2. It requires that the 843 port of the firewall is open so that the flash component can issue an HTTP request to retrieve the policy file that contains the domain authorization. If the 843 port is unreachable, the library should have a fallback action or give an error, all of which will take some time (up to 3 seconds, depending on the library), which slows down the site.

3. If the client is behind a proxy server, the connection to port 843 may be denied.

The WEBSOCKETJS project provides a bridging approach that requires a minimum of 10 versions of Flash to provide websocket support for Firefox 3, inernet Explorer 8, and Internet Explorer 9.

  Suggestions

It brings more benefits than comet,websocket. In daily development, the client supports websocket faster and produces fewer requests (thus consuming less bandwidth). However, since not all browsers support WebSocket, the best option for reverse Ajax libraries is to be able to detect support for websocket, and to fall back to Comet (long polling) if WebSocket is not supported.

Since both technologies require best practices and compatibility from all browsers, my recommendation is to use a client-side JavaScript library that provides an abstraction layer on top of these technologies. Sections 3rd and 4 of this series explore some libraries, and the 5th part describes their applications. On the server side, as discussed in the next section, things are slightly more complicated.

  Reverse AJAX constraints on the server side

Now that you have an overview of the reverse AJAX solution available to clients, let's look at the reverse Ajax solution on the server side. So far, the examples have mostly been the client's JavaScript code. On the server side, to accept a reverse Ajax connection, some techniques require specific functionality to handle long-lived connections compared to the short HTTP requests you are familiar with. For better scalability, you should use a new threading model that requires a specific API in Java to pause the request. Also, for WebSocket, you have to properly manage the scope of the services used in your app.

  Thread and non-blocking I/O

Typically, a Web server associates a thread or a process with each incoming HTTP connection. This connection can be persistent (keep active) so that multiple requests can be made through the same connection. In the example in this article, the Apache Web server can be configured as a mpm_fork or Mpm_worker mode to change this behavior. The Java Web server (the application server is also included-this is the same thing) typically uses a separate thread for each incoming connection.

Generating a new thread can lead to memory consumption and resource waste, as it does not guarantee that the resulting thread will be used. The connection may be established, but no data from the client or server side is sent. Regardless of whether this thread is used, it consumes both memory and CPU resources for scheduling and context switching. Also, when you use threading mode to configure a server, you typically need to configure a thread pool (set the maximum number of threads that handle incoming connections). If the value is improperly configured and the value is too small, you will end up with thread starvation, and the request will remain in the waiting state until the threads are available to process them, and the response time will drop when the maximum concurrent connection is reached. On the other hand, configuring a high value can result in an out-of-memory exception, resulting in multithreading that consumes all available heaps of the JVM, causing the server to crash.

Java recently introduced a new I/O API, called non-blocking I/O. This API uses a selector to avoid the practice of binding a thread each time a new HTTP connection is established on the server side, and when there is data coming, an event is received and a thread is assigned to process the request. Therefore, this practice is called one thread per request (Thread-per-request) mode. It allows Web servers, such as WebSphere and jetty, to use a fixed number of threads to accommodate and handle more and more user connections. In the case of the same hardware configuration, the scalability of the Web server running in this mode is much better than running under each connected one thread (thread-per-connection) model.

In the blog of Philip McCarthy (Comet and Reverse Ajax author), there is an interesting benchmark for the scalability of both threading patterns (see Resources for links). In Figure 2, you will find the same pattern: when there are too many connections, the threading mode stops working.

Figure 2. Metrics for threading Patterns

Each connection to a threading pattern (threads in Figure 2) usually has a better response time because all threads are started, ready and waiting, but when the number of connections is too high, it stops serving. In each request for a threading pattern (continuations in Figure 2), the thread is used to service the requested arrival, and the connection is handled by a NIO selector. The response time may be slower, but the thread is recycled, so the scheme has better scalability in terms of high-capacity connectivity.

To understand how threads work behind the scenes, you can think of a lego™ block as a selector, which is identified by a pin each time an incoming connection arrives at the Lego block. Lego blocks/selectors have as many pins as the number of connections (as many keys). Then, just one thread is required to wait for the new event to occur, and then to traverse on those pins. When something happens, the selector thread retrieves the key value from the event that occurred, and then it can use a thread to service the incoming request.

The "Rox Java NIO Tutorial" Tutorial has a good example of using NIO in Java (see Resources).

  Service with request scope

Many frameworks provide services or filters to handle Web requests that reach the servlet, for example, a filter that:

1. Bind the JDBC connection to a request thread so that the entire request uses only one connection.

2. Submit the changes at the end of the request.

Another example is the Guice servlet extension of Google Guice (a Dependency injection library). Similar to Spring,guice, a service can be bound to a requested scope, and an instance is created only once for each new request (see Resources for more information).

The usual practice involves using a user ID to cache user objects retrieved from the repository in the request, and the user ID is taken from the clustered HTTP session. In Google Guice, you might have code like the one given in Listing 7.

Listing 7. Request-scoped Bindings

@Provides
@RequestScoped
Member Member (AuthManager AuthManager,
Memberrepository memberrepository) {
Return Memberrepository.findbyid (Authmanager.getcurrentuserid ());
}

When a member is injected into the class, Guice attempts to get the object from the request and, if not found, executes the repository call and puts the result in the request.

The request scope can be used with any reverse Ajax solution other than WebSocket, and any other solution that relies on HTTP requests, whether short or long, can be distributed through the servlet, and the filter will be executed. When you complete a paused (long-lived) HTTP request, you will learn in the subsequent sections of this series that there is another way to make the request pass through the filter chain again.

For WebSocket, the data is directly on the onmessage callback function, as in the case of the TCP socket interface. There is no HTTP request to service this data, so there is no request context to get or store the scope object. Therefore, using a service that requires a scope object in the OnMessage callback will fail. The Guice-and-websocket example in the downloadable source code illustrates how to circumvent this restriction so that the request scope object can still be used in the OnMessage callback. When you run this example and click on each button on the Web page to test an AJAX call (with request scope), a websocket call, and a websocket call that uses the scope of the impersonation request, you get the output shown in Figure 3.

Figure 3. WebSocket handler that uses the request scope service

You may encounter these problems when using either of the following technologies:

1. Spring

2. Hibernate

3. Any other framework that requires a request scope or each request model, such as Opensessioninviewfilter.

4. Use the Threadlocal facility inside the filter to specify the scope of the variable as the request thread and the system that accesses the variables at a later time.

Guice has an elegant solution, as shown in Listing 8:

Listing 8. Simulating a request scope in the OnMessage callback of WebSocket

When calling Dowebsocketmethod
Save to the requested reference
HttpServletRequest request = [...]
Map, object> bindings =new HashMap, object> ();
I have a service that requires a request to get a session
So I offer a request, but you can provide any other
Bindings that may be required
Bindings.put (Key.get (httpservletrequest.class), request);
Servletscopes.scoperequest (New callable () {
@Override
Public Object Call () throws Exception {
Call your repository or any service that uses a scope object
Outbound.sendmessage ([...]);
return null;
}
}, Bindings). Call ();

  Pause Long Lifetime Requests

If you use Comet, there is another hurdle, which is how the server can pause a long-lived request without impacting performance, and then recover and complete the request as soon as the server-side event arrives.

Obviously, you can't simply let requests and responses stop there, which can cause thread starvation and high memory consumption. Pauses a long-lived request in non-blocking I/O, which in Java requires a unique API. The Servlet 3.0 specification provides such an API (see part 1th of this series). Listing 9 shows an example.

Listing 9. To define an asynchronous servlet using Servlet 3.0来

<?xml version= "1.0" encoding= "UTF-8"?>

<web-app version= "3.0" xmlns= "Http://java.sun.com/xml/ns/javaee"
Xmlns:j2ee= "Http://java.sun.com/xml/ns/javaee"
Xmlns:xsi= "Http://www.w3.org/2001/XMLSchema-instance"
xsi:schemalocation= "Http://java.sun.com/xml/ns/j2ee Http://java.sun.com/xml
/ns/j2ee/web-app_3.0.xsd ">

<servlet>
<servlet-name>events</servlet-name>
<servlet-class>ReverseAjaxServlet</servlet-class>
<async-supported>true</async-supported>
</servlet>

<servlet-mapping>
<servlet-name>events</servlet-name>
<url-pattern>/ajax</url-pattern>
</servlet-mapping>

</web-app>

After you have defined an asynchronous servlet, you can use the Servlet 3.0 API to suspend and resume a request, as shown in Listing 10:

Listing 10. Suspend and resume a request

Asynccontext Asynccontext = Req.startasync ();
Keep a reference to the asynccontext somewhere

And then, when needed, in another thread you can recover and complete
HttpServletResponse req =
(HttpServletResponse) asynccontext.getresponse ();
Req.getwriter (). Write ("Data");
Req.setcontenttype ([...]);
Asynccontext.complete ();

Before Servlet 3.0, each container had and still has its own mechanism. The continuation of jetty (continuation) is a well-known example, and many of the reverse Ajax libraries in Java rely on jetty continuation. It's not a fantastic practice, and it doesn't require your application to run on a jetty container. The smart thing about the API is that it detects the containers you're running, and if it's running on another container, such as Tomcat or grizzly, then fallback to the Servlet 3.0 API if the Servlet 3.0 API is available. This is no problem for comet, but if you want to take advantage of WebSocket, there is currently no choice but to use container-specific features only.

The Servlet 3.0 specification has not yet been published, but many containers have implemented this API because it is also a standard practice for implementing reverse Ajax.

  Conclusion

WebSocket Although there are some shortcomings, but it is a very powerful reverse Ajax solution. It is not currently implemented on all browsers and is not easy to use on the Java server without the help of a reverse Ajax library. Because you're not using the standard request-response style, all you can't rely on is the scope of the filter chain to execute. Comet and WebSocket require server-side container-specific functionality, so when you use a new container, you need to be aware that it may not be expanding in this area.

Keep your eye on the 3rd part of this series, which will explore the different server-side APIs for Comet and WebSocket, and you can also learn about Atomsphere, a reverse AJAX framework.

  Download

Description Name Size Download method

Article source code for Reverse_ajaxpt2_source.zip 14KB HTTP

  Resources

1. "Start using HTML5 WebSockets Today" (nettuts+): Relive how a websocket server is running in PHP and consider how to build a client to send and receive messages through the WebSocket protocol.

2. "The WebSocket API" (July 2011): This specification-defined API enables Web pages to communicate with remote hosts in two-way using the WebSocket protocol.

3. Jwebsocket supported Browsers: Learn about the various aspects of the browser supported by the Jwebsocket and Flash socket interface bridges.

4. Learn more about the support of Servlet 3.0 for asynchronous processing.

5. Philip McCarthy's blog article on Comet & java:threaded Vs nonblocking I/O has more content.

6. The Rox Java NiO Tutorial This tutorial collects some of the experience of authors using the Java NiO library, along with dozens of tips, tricks, recommendations, and cautionary practices that are rife with the Internet.

7. Learn about the content on Wikipedia:

7.1 Ajax
7.2 Reverse Ajax
7.3 Comet
7.4 WebSockets

8. "Exploring Reverse Ajax" (Google Maps. Net Control Blog, August 2006): Get some introductory notes on reverse AJAX technology.

9. "Cross-domain Communications with JSONP, part 1:combine JSONP and JQuery to quickly build powerful mashups" (developerw Orks, February 2009): Learn how to combine the humble cross-domain call technology (JSONP) with a flexible JavaScript library (JQuery) to build some powerful aggregation applications at an astonishing speed.

"Cross-origin Resource Sharing (CORS)" Specification (Global, July 2010): Learn more about this mechanism, which allows XHR to perform cross-domain requests.

"Build Ajax applications with Ext JS" (DeveloperWorks, July 2008): There is a general understanding of this framework that greatly enhances JavaScript development.

"Compare JavaScript Frameworks" (DeveloperWorks, February 2010): A holistic understanding of those frameworks that greatly enhance JavaScript development.

"Mastering Ajax, part 2:make asynchronous requests with JavaScript and Ajax" (DeveloperWorks, January 2006): Learn how to use Ajax and XMLHttpRequest objects to create a request/response model that will never let the user wait for the server to respond.

"Create Ajax applications for the mobile Web" (DeveloperWorks, March 2010): Learn how to build a cross-browser smartphone web App using Ajax.

The "Where and when" uses Ajax in your Applications "(DeveloperWorks, February 2008): Learn how to improve your website with Ajax while avoiding a bad user experience.

"Improve the performance of WEB 2.0 Applications" (DeveloperWorks, December 2009): Explore different browser-side caching mechanisms.

"Introducing JSON" (json.org): Get an introductory introduction to JSON syntax.

DeveloperWorks Web Development Zone: Get a variety of articles that talk about Web-based solutions.

DeveloperWorks Podcasts: Listen to a variety of interesting interviews and discussions with software developers.

DeveloperWorks Technical Events and Webcasts: Stay tuned for DeveloperWorks's technical events and webcast progress.

  Access to products and technologies

1. Websocketjs (WebSocket Flash Bridge): Get this HTML5 WebSocket implementation supported by Flash.

2. Google Guice: Get Google Guice, a lightweight dependency injection framework for Java 5 and later.

3. Jetty: Get Jetty, a Web server and Javax.servlet container, with support for WebSocket.

4. Apache maven: Get maven, a software project management and Containment tool.

5. Java Development Kit, version 6: Get Java Platform Standard Edition (Java Platform, Standards Edition,java SE), which allows you to be on desktops and servers, and the development and deployment of Java applications in today's demanding embedded environments.

6. Free trial of IBM software, download the use version, log in to the online trial, use the product in a sandbox environment, or access via work with with over 100 IBM Product trial options.

  Discuss

1. Create your Developerworks profile now and set up a watch list of reverse Ajax. Connect with the Developerworks community and stay connected.

2. Find other Developerworks members who are interested in web development.

3. Share your knowledge: Join a developerworks group that focuses on web topics.

4. Roland Barcia in his blog about Web 2.0 and middleware.

5. Follow the Developerwork member's shared bookmarks on web topics.

6. Get answers quickly: Visit the Web 2.0 Apps forum.

7. Get answers quickly: Visit the AJAX Forum.

Reverse Ajax, part 2nd: WebSocket

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.