Reverse Ajax, Phần 3: Các máy chủ Web và Socket.IO

Sử dụng các web container, các API và các thư viện trừu tượng

Loạt bài này tìm hiểu cách phát triển các ứng dụng web theo hướng sự kiện bằng cách sử dụng các kỹ thuật Reverse Ajax. Phần 1 đã giới thiệu các cách khác nhau để thực hiện truyền thông Reverse Ajax: polling, piggyback, Comet long-polling và Comet streaming. Phần 2 đã giải thích cách thực hiện Reverse Ajax bằng cách sử dụng WebSockets và đã thảo luận về những hạn chế của các máy chủ web khi sử dụng Comet và WebSockets. Trong bài này, hãy tìm hiểu cách sử dụng Comet và WebSockets trong ứng dụng web của bạn với các API và các web container khác nhau. Ngoài ra tìm hiểu về Socket.IO, một thư viện trừu tượng hóa có thể được sử dụng trong một ứng dụng web với Reverse Ajax. Các thư viện trừu tượng hóa, có thể được sử dụng trong suốt, ẩn giấu tất cả sự phức tạp đằng sau Comet và WebSockets.

Mathieu Carbou, Kiến trúc sư Java Web, Ovea

Ảnh của Mathieu CarbouMathieu Carbou là nhà tư vấn và kiến trúc web Java ở Ovea, cung cấp các dịch vụ và các giải pháp phát triển. Ông là người đứng dầu và điều hành một số dự án nguồn mở, là người phát ngôn và lãnh đạo của Nhóm người dùng Java (Java User Group) của Montreal. Mathieu có nền tảng vững chắc về thiết kế mã và có kinh nghiệm tốt, ông còn là một chuyên gia phát triển web theo hướng sự kiện (event-driven web) từ phía máy khách đến các tầng bên dưới. Ông tập trung vào việc cung cấp các giải pháp thông tin và theo hướng sự kiện của các ứng dụng web có khả năng co giãn cao. Hãy ghé thăm blog của ông.



23 01 2013

Giới thiệu

Người dùng hiện nay mong đợi các ứng dụng linh động, nhanh chóng có thể truy cập được từ trang web. Loạt bài này cho bạn thấy cách phát triển các ứng dụng web theo hướng sự kiện bằng cách sử dụng các kỹ thuật Reverse Ajax. Phần 1 đã giới thiệu Reverse Ajax, polling, streaming, Comet, long-polling. Bạn đã tìm hiểu vì sao Comet sử dụng HTTP long-polling là cách tốt nhất để thực hiện Reverse Ajax, khi hiện nay tất cả các trình duyệt đều hỗ trợ nó. Phần 2 đã mô tả cách thực hiện Reverse Ajax bằng cách sử dụng WebSockets. Các ví dụ mã giúp minh họa các ràng buộc WebSockets, FlashSocket bên phía máy chủ, các dịch vụ phạm vi-yêu cầu, và cách để tạm dừng các yêu cầu long-lived.

Trong bài này, hãy đi chi tiết về cách sử dụng Comet và WebSockets trong ứng dụng web của bạn với các API và các web container khác nhau (Servlet 3.0 và Continuations của Jetty). Hãy tìm hiểu cách sử dụng Comet và WebSockets một cách trong suốt bằng cách sử dụng các thư viện trừu tượng hóa, chẳng hạn như Socket.IO. Socket.IO sử dụng tính năng nhận dạng để quyết định xem kết nối đó sẽ được thiết lập với WebSocket, AJAX long-polling, Flash và v.v hay không.

Bạn có thể tải về mã nguồn được sử dụng trong bài này.

Điều kiện tiên quyết

Tốt nhất bạn nên biết trước về JavaScript và Java. Các ví dụ trong bài này đã được xây dựng bằng cách sử dụng Google Guice, một framework tích hợp phụ thuộc (dependency injection framework) được viết bằng Java. Để làm theo cùng với bài này, bạn nên hiểu rõ các khái niệm về dependency injection framework, chẳng hạn như Guice, Spring hoặc Pico.

Để chạy được các ví dụ trong bài này, bạn cần có phiên bản mới nhất của Maven và JDK (xem phần Tài nguyên).


Các giải pháp máy chủ cho Comet và WebSocket

Phần 1, bạn đã tìm hiểu về phương pháp Comet (long-polling hay streaming) có khả năng yêu cầu máy chủ có thể tạm dừng một request và tiếp tục hay hoàn thành nó sau một thời gian nắm giữ. Phần 2 đã mô tả cách mà máy chủ cần sử dụng tính năng I/O non-blocking như thế nào để xử lý nhiều kết nối và chúng chỉ sử dụng các luồng để phục vụ các yêu cầu (mô hình luồng cho mỗi yêu cầu). Bạn cũng đã biết rằng việc sử dụng WebSocket phụ thuộc vào máy chủ và không phải tất cả các máy chủ đều hỗ trợ WebSockets.

Phần này sẽ cho bạn thấy cách sử dụng Comet và WebSockets, nếu có, trên các máy chủ web Jetty, Tomcat và Grizzly. Mã nguồn được cung cấp cùng với bài này có một ứng dụng web chat (trò chuyện trực tuyến) là ví dụ mẫu cho Jetty và Tomcat. Phần này cũng thảo luận về các API hỗ trợ cho các máy chủ ứng dụng sau: Jboss, Glassfish và WebSphere.

Jetty

Jetty là một máy chủ web hỗ trợ đặc tả Java Servlet 3.0, WebSockets và nhiều đặc tả tích hợp khác. Jetty là:

  • Mạnh mẽ và linh hoạt.
  • Dễ dàng nhúng.
  • Hỗ trợ các máy chủ ảo, phân cụm session và rất nhiều tính năng có thể được cấu hình dễ dàng thông qua mã Java hoặc XML.
  • Được dùng cho dịch vụ lưu trữ của Google App Engine.

Dự án Jetty được quản lý bởi Quỹ Eclipse.

Kể từ phiên bản 6, Jetty bao gồm một API không đồng bộ được gọi là Jetty Continuations, cho phép một yêu cầu được tạm dừng và có thể tiếp tục lại sau đó. Bảng 1 cho thấy bản đồ về đặc tả và API hỗ trợ với các họ phiên bản Jetty chính.

Bảng 1. Các phiên bản Jetty và khả năng hỗ trợ
Các sự hỗ trợJetty 6Jetty 7Jetty 8
Non-blocking I/OXXX
Servlet 2.5XXX
Servlet 3.0XX
Jetty Continuations (Comet)XXX
WebSocketsXX

Để thực hiện Reverse Ajax với Comet, bạn có thể sử dụng các API Continuation của Jetty, như thể hiện trong Liệt kê 1:

Liệt kê 1. API Continuation của Jetty cho Comet
// Pausing a request from a servlet's method (get, post, ...):

protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
        throws ServletException, IOException { 

Continuation continuation = ContinuationSupport.getContinuation(req); 
// optionally set a timeout to avoid suspending requests for too long 
continuation.setTimeout(0); 
// suspend the request 
continuation.suspend(); 
// then hold a reference for future usage from another thread 
continuations.offer(continuation); 

}

// Then, from another thread which wants to send an event to the client:

while (!continuations.isEmpty()) { 
    Continuation continuation = continuations.poll(); 
    HttpServletResponse response = 
        (HttpServletResponse) continuation.getServletResponse(); 
    // write to the response 
    continuation.complete(); 
}

Ứng dụng web hoàn chỉnh có trong mã nguồn đi kèm với bài này. Jetty Continuations được đóng gói trong một tệp JAR. Bạn phải đặt tệp JAR này trong thư mục WEB-INF/lib của ứng dụng web của mình để có thể sử dụng các tính năng Comet của Jetty. Continuations của Jetty sẽ làm việc trên Jetty 6, 7 và 8.

Bắt đầu với Jetty 7, bạn cũng có quyền truy cập vào tính năng WebSockets. Đặt tệp JAR WebSocket của Jetty vào thư mục WEB-INF/lib của ứng dụng web của bạn để có quyền truy cập vào API WebSocket của Jetty, như trong Liệt kê 2:

Liệt kê 2. API WebSocket của Jetty
// Implement the  doWebSocketConnect and returns an implementation of
//  WebSocket:

public final class ReverseAjaxServlet extends WebSocketServlet { 
    @Override 
    protected WebSocket doWebSocketConnect(HttpServletRequest request,
                                           String protocol) { 
        return [...] 
    } 
}

// Sample implementation of  WebSocket:

class Endpoint implements WebSocket { 
    Outbound outbound; 
    public void onConnect(Outbound outbound) { 
        this.outbound = outbound;    
    } 
    public void onMessage(byte opcode, String data) { 
        outbound.sendMessage("Echo: " + data);
        if("close".equals(data)) 
             outbound.disconnect();
    } 
    public void onFragment(boolean more, byte opcode, 
                           byte[] data, int offset, int length) { 
    } 
    public void onMessage(byte opcode, byte[] data, 
                          int offset, int length) { 
        onMessage(opcode, new String(data, offset, length)); 
    } 
    public void onDisconnect() { 
        outbound = null; 
    } 
}

Trong thư mục jetty-websocket củamã nguồn có một ví dụ chat mẫu để trình bày cách sử dụng API WebSocket của Jetty.

Tomcat

Có lẽ Tomcat là máy chủ web nổi tiếng nhất. Nó đã được sử dụng trong nhiều năm và đã được tích hợp như là một web container vào các phiên bản đầu tiên của máy chủ ứng dụng Jboss. Ngoài ra, Tomcat còn được dùng cho việc thực thi tham khảo đặc tả servlet. Nó đã được loại bỏ khỏi phiên bản API servlet 2.5 khi mọi người bắt đầu xem xét các lựa chọn thay thế dựa trên I/O non-blocking (như Jetty). Bảng 2 cho thấy API và các đặc tả được hỗ trợ cho hai họ phiên bản Tomcat mới nhất.

Bảng 2. Sự hỗ trợ của Tomcat
Các sự hỗ trợTomcat 6Tomcat 7
Non-blocking I/OXX
Servlet 2.5XX
Servlet 3.0X
Advanced I/O (Comet)XX
WebSockets

Như thể hiện trong Bảng 2, Tomcat không hỗ trợ WebSockets; nó có một bản tương đương với Continuations của Jetty được gọi là I/O nâng cao (Advanced I/O) để hỗ trợ Comet. I/O nâng cao là một trình bao bọc mức thấp xung quanh NIO mạnh hơn một API tốt để làm cho việc sử dụng Comet dễ dàng hơn. Nó có ít tài liệu và chỉ có một vài ví dụ mô tả cách sử dụng API này. Liệt kê 3 cho thấy một ví dụ về servlet được sử dụng để treo và tiếp tục lại các yêu cầu trong một ứng dụng web chat. Bạn có thể tìm thấy ứng dụng web hoàn chỉnh trong mã nguồn đi kèm với bài này.

Liệt kê 3. API của Tomcat cho Comet
public final class ChatServlet extends HttpServlet 
                               implements CometProcessor { 

    private final BlockingQueue<CometEvent> events = 
         new LinkedBlockingQueue<CometEvent>(); 

    public void event(CometEvent evt) 
        throws IOException, ServletException { 

        HttpServletRequest request = evt.getHttpServletRequest(); 
        String user = 
            (String) request.getSession().getAttribute("user"); 
        switch (evt.getEventType()) { 
            case BEGIN: { 
                if ("GET".equals(request.getMethod())) { 
                    evt.setTimeout(Integer.MAX_VALUE); 
                    events.offer(evt); 
                } else { 
                    String message = request.getParameter("message"); 
                    if ("/disconnect".equals(message)) { 
                        broadcast(user + " disconnected"); 
                        request.getSession().removeAttribute("user"); 
                        events.remove(evt); 
                    } else if (message != null) { 
                        broadcast("[" + user + "]" + message); 
                    } 
                    evt.close(); 
                } 
            } 
        } 
    } 

    void broadcast(String message) throws IOException { 
        Queue<CometEvent> q = new LinkedList<CometEvent>(); 
        events.drainTo(q); 
        while (!q.isEmpty()) { 
            CometEvent event = q.poll(); 
            HttpServletResponse resp = event.getHttpServletResponse();
            resp.setStatus(HttpServletResponse.SC_OK);
            resp.setContentType("text/html");
            resp.getWriter().write(message);
            event.close(); 
        } 
    } 
}

Trong Tomcat, một servlet không đồng bộ phải thực hiện một CometProcessor. Đối với các servlet không đồng bộ, Tomcat không gọi các phương thức HTTP tiêu chuẩn (doGet, doPost và v.v). Thay vào đó, nó gửi một sự kiện đến phương thức event(CometdEvent). Khi yêu cầu đầu tiên gửi đến, ví dụ sẽ kiểm tra để xem liệu nó có là một GET để treo nó không; evt.close() không được gọi. Nếu nó là một POST, có nghĩa là người dùng đã gửi một thông báo, do đó, nó được broadcast (phát hàng loạt) đến CometEvent khác và evt.close() được gọi để hoàn thành yêu cầu đăng thông báo. Về phía máy khách, việc broadcast sẽ thực hiện tất cả các yêu cầu long-polling để hoàn thành thông báo đã gửi và một yêu cầu long-polling khác được gửi ngay để nhận được các sự kiện tiếp theo.

Grizzly và Glassfish

Grizzly không phải là web container, nhưng hơn một framework NIO giúp các nhà phát triển xây dựng các ứng dụng có khả năng co giãn. Nó được phát triển như là một phần trong dự án Glassfish, nhưng nó cũng có thể được sử dụng độc lập hoặc nhúng vào hệ thống khác. Grizzly cung cấp các thành phần như một máy chủ HTTP/HTTPS và các thành phần cho Bayeux Protocol, Servlet, HTTPService OSGi và Comet, trong số những thứ khác. Grizzly hỗ trợ WebSockets và được sử dụng trong Glassfish để cung cấp Comet và hỗ trợ WebSocket.

Glassfish, Application Server (Máy chủ ứng dụng) của Oracle, là cách thực hiện tham khảo của các đặc tả J2EE 6. Glassfish là một gói hoàn chỉnh, như WebSphere và Jboss, khi sử dụng Grizzly để hỗ trợ NIO, WebSocket và Comet. Kiến trúc mô đun của nó, dựa trên OSGI, giúp nó linh hoạt trong việc thay đổi các thành phần. Bảng 3 cho thấy Glassfish hỗ trợ Comet và WebSockets.

Bảng 3. Sự hỗ trợ của Glassfish
Các sự hỗ trợGlassfish 2Glassfish 3
Non-blocking I/OXX
Servlet 2.5XX
Servlet 3.0X
CometXX
WebSocketsX

Cách sử dụng Grizzly cũng rất quan trọng, khi người ta dự định sử dụng nó theo cách nhúng hoặc trực tiếp từ mã Java. Nó được sử dụng rộng rãi như một framework để hỗ trợ Comet và WebSockets, mà nó có thể được nhúng trong một ứng dụng lớn hơn, ví dụ như Glassfish, cung cấp các khả năng triển khai web và API đặc tả Servlet.

Xem phần Tài nguyên để biết các liên kết đến các ví dụ của WebSockets và Comet trong Grizzly hoặc Glassfish. Vì Glassfish sử dụng Grizzly, nên các ví dụ sẽ làm việc trên cả hai. API WebSocket cũng rất giống như một API trong Jetty, nhưng API của Comet phức tạp hơn.

Jboss

Jboss là một máy chủ ứng dụng được xây dựng dựa trên Tomcat. Nó đã hỗ trợ Comet và NIO kể từ phiên bản 5. Jboss 7 vẫn còn đang phát triển, nhưng được đưa vào trong Bảng 4 dưới đây.

Bảng 4. Sự hỗ trợ của Jboss
Các sự hỗ trợJboss 5Jboss 6Jboss 7
Non-blocking I/OXXX
Servlet 2.5XXX
Servlet 3.0XX
CometXXX
WebSockets

WebSphere

WebSphere là một máy chủ ứng dụng của IBM. Phiên bản 8 của WebSphere đã hỗ trợ của API Servlet 3 (có chứa API không đồng bộ tiêu chuẩn hóa cho Comet) (xem phần Tài nguyên để đọc thông báo).

Bảng 5. Sự hỗ trợ của WebSphere
Các sự hỗ trợWebSphere 8
Non-blocking I/OX
Servlet 2.5X
Servlet 3.0X
CometX
WebSockets

Thế còn các API chung thì như thế nào?

Mỗi máy chủ đưa ra API nguyên gốc của riêng mình cho Comet và WebSocket. Như bạn có thể đoán là việc viết một ứng dụng web di động có thể khó khăn. Đặc tả Servlet 3.0 gồm có các phương thức bổ sung để treo và tiếp tục lại một yêu cầu sau đó, cho phép tất cả các web container hỗ trợ Đặc tả Servlet 3.0 đều hỗ trợ các yêu cầu Comet long-polling.

Nhóm phát triển Jetty cung cấp một thư viện được gọi là Continuation của Jetty, độc lập với Jetty container. Thư viện Continuation của Jetty đủ thông minh để phát hiện ra container hoặc đặc tả có sẵn. Nếu bạn đang chạy trên một máy chủ Jetty, API của Jetty nguyên gốc sẽ được sử dụng. Nếu bạn đang chạy trên một container hỗ trợ Đặc tả Servlet3.0, API chung (common API) này sẽ được sử dụng. Nếu không, việc thực hiện không có khả năng co giãn sẽ được sử dụng.

Về WebSockets, vẫn chưa có tiêu chuẩn nào trong Java và do đó bạn cần sử dụng API container của nhà cung cấp trong ứng dụng web của mình nếu bạn muốn sử dụng WebSockets.

Bảng 6 tóm tắt các công nghệ được các máy chủ khác nhau hỗ trợ.

Bảng 6. Các công nghệ được các máy chủ hỗ trợ
ContainerCometWebSocket
Jetty 6Jetty ContinuationsKhông có
Jetty 7Servlet 3.0
Jetty Continuations
Native Jetty API (API Jetty nguyên gốc)
Jetty 8Servlet 3.0
Jetty Continuations
Native Jetty API
Tomcat 6Advanced I/O (Vào/ra nâng cao)Không có
Tomcat 7Servlet 3.0
Advanced I/O
Jetty Continuations
Không có
Glassfish 2Native Grizzly API (API Grizzly nguyên gốc)Không có
Glassfish 3Servlet 3.0
Native Grizzly API
Jetty Continuations
Native Grizzly API
Jboss 5Native Jboss API (API Jboss nguyên gốc)Không có
Jboss 6Servlet 3.0
Native Jboss API
Jetty Continuations
Không có
Jboss 7Servlet 3.0
Native Jboss API
Jetty Continuations
Không có
WebSphere 8Servlet 3.0
Jetty Continuations
Không có

Không có giải pháp rõ ràng nào cho WebSockets ngoại trừ việc sử dụng API container. Như với Comet, mỗi container hỗ trợ Đặc tả Servlet 3.0 đều hỗ trợ Comet. Ở đây lợi thế của Jetty Continuations là cung cấp hỗ trợ Comet trên tất cả các container này. Vì vậy, một số thư viện Reverse Ajax (được tiếp tục thảo luận dưới đây và trong phần tiếp theo của loạt bài này) đang sử dụng Jetty Continuations API phía máy chủ.

API Jetty Continuation được hiển thị trong ví dụ mẫu trong bài này. Đặc tả Servlet 3.0 đã được mô tả và được sử dụng trong hai ví dụ Comet trong Phần 1 của loạt bài này.


Các thư viện trừu tượng hóa

Khi xem xét tất cả các API chủ yếu (Servlet 3.0 và Jetty Continuations), cộng với tất cả sự hỗ trợ bên phía máy chủ và hai cách chủ yếu để thực hiện Reverse Ajax bên phía máy khách (Comet và WebSocket) sẽ thấy thật khó để viết JavaScript và mã Java riêng của bạn để nối chúng lại với nhau. Bạn cũng phải tính đến các yếu tố như thời gian chờ timeout, các lỗi kết nối, tin báo nhận, chỉ dẫn, giữ dữ liệu trong bộ đệm và v.v.

Phần còn lại của bài này sẽ cho bạn thấy Socket.IO hoạt động như thế nào. Phần 4 của loạt bài này sẽ tìm hiểu Atmosphere và CometD. Tất cả ba thư viện này đều là nguồn mở và tất cả chúng đều hỗ trợ Comet và WebSocket trên nhiều máy chủ.

Socket.IO

Socket.IO là một thư viện máy khách JavaScript cung cấp một API riêng, tương tự như WebSocket, để kết nối đến một máy chủ từ xa để gửi và nhận thông báo không đồng bộ. Bằng cách cung cấp một API chung, Socket.IO hỗ trợ một số kiểu truyền tải: WebSocket, Flash Sockets, long-polling, streaming, forever Iframes (Các khung nội tuyến vô hạn) và JSONP polling. Socket.IO phát hiện ra các khả năng của trình duyệt và cố gắng lựa chọn kiểu truyền tải tốt nhất có thể. Thư viện Socket.IO tương thích với hầu hết tất cả các trình duyệt (bao gồm cả các trình duyệt cũ, chẳng hạn như IE 5.5) cũng như các trình duyệt di động. Nó cũng có các tính năng như các nhịp hoạt động (heartbeat), thời gian chờ, ngắt kết nối và xử lý lỗi.

Trang web Socket.IO (xem phần Tài nguyên) mô tả chi tiết thư viện này hoạt động ra sao và trình duyệt và kỹ thuật Reverse Ajax nào được sử dụng. Về cơ bản, Socket.IO sử dụng một giao thức truyền thông cho phép thư viện máy khách truyền thông với một điểm cuối ở phía máy chủ, mà điểm này có thể hiểu được giao thức Socket.IO. Đầu tiên người ta phát triển Socket.IO cho Node JS, một công cụ JavaScript được sử dụng để xây dựng các máy chủ nhanh hơn. Nhưng giờ đây, nhiều dự án đã mang đến sự hỗ trợ cho các ngôn ngữ khác, bao gồm cả Java.

Liệt kê 4 cho thấy một ví dụ về sử dụng thư viện JavaScript Socket.IO bên phía máy khách. Trang web Socket.IO có tài liệu hướng dẫn và các ví dụ.

Liệt kê 4. Sử dụng thư viện máy khách Socket.IO
var socket = new io.Socket(document.domain, { 
    resource: 'chat' 
}); 
socket.on('connect', function() { 
    // Socket.IO is connected
}); 
socket.on('disconnect', function(disconnectReason, errorMessage) { 
    // Socket.IO disconnected
}); 
socket.on('message', function(mtype, data, error) { 
    // The server sent an event
});

// Now that the handlers are defined, establish the connection:
socket.connect();

Để sử dụng thư viện JavaScript Socket.IO, bạn sẽ cần một thành phần Java tương ứng được gọi là Socket.IO Java (xem phần Tài nguyên). Ban đầu dự án này được nhóm công tác Apache Wave khởi động để đem đến sự hỗ trợ Reverse Ajax cho Wave trước khi WebSockets được hỗ trợ. Socket.IO Java được chia làm hai nhánh và được duy trì bởi Ovea (một công ty chuyên về phát triển web theo hướng sự kiện) và sau đó bị bỏ rơi. Việc phát triển tầng sau để hỗ trợ thư viện máy khách Socket.IO có phức tạp là do có nhiều kiểu truyền tải. Phần 4 của loạt bài này sẽ chỉ ra vì sao việc hỗ trợ nhiều kiểu truyền tải trong một thư viện máy khách là không cần thiết để đạt được khả năng co giãn và hỗ trợ trình duyệt tốt hơn, do chỉ cần long-polling và WebSockets là đủ. Khi chưa hỗ trợ WebSockets, Socket.IO đã là một lựa chọn tốt.

Socket.IO Java sử dụng API Jetty Continuation để treo và tiếp tục lại các yêu cầu. Nó sử dụng API WebSockets của Jetty nguyên gốc để hỗ trợ WebSockets. Bạn có thể xác định máy chủ nào sẽ làm việc đúng với một ứng dụng web khi sử dụng Socket.IO Java.

Liệt kê 5, dưới đây, cho thấy một ví dụ về cách sử dụng Socket.IO trên máy chủ. Bạn phải định nghĩa một SocketIOServlet mở rộng của servlet và thực hiện một phương thức để trả về một loại đại diện điểm cuối. API này rất giống với API WebSockets. Ưu điểm là ở chỗ API này được sử dụng bên phía máy chủ, độc lập với việc truyền tải được chọn bên phía máy khách. Socket.IO chuyển dịch tất cả các kiểu truyền tải tới API tương tự bên phía máy chủ.

Liệt kê 5. Thư viện Socket.IO Java được sử dụng cho ví dụ mẫu chat - servlet
public final class ChatServlet extends SocketIOServlet { 
    private final BlockingQueue<Endpoint> endpoints = 
        new LinkedBlockingQueue<Endpoint>(); 
 
    @Override 
    protected SocketIOInbound doSocketIOConnect
                                        (HttpServletRequest request) { 
        String user = 
                (String) request.getSession().getAttribute("user"); 
        return user == null ? null : new Endpoint(this, user, request); 
    } 
 
    void broadcast(String data) { 
        for (Endpoint endpoint : endpoints) { 
            endpoint.send(data); 
        } 
    } 
 
    void add(Endpoint endpoint) { 
        endpoints.offer(endpoint); 
    } 
 
    void remove(Endpoint endpoint) { 
        endpoints.remove(endpoint); 
    } 
}

Liệt kê 6 cho thấy cách trả về điểm cuối.

Liệt kê 6. Sử dụng thư viện Socket.IO Java cho ví dụ mẫu chat - điểm cuối
class Endpoint implements SocketIOInbound { 
 
    [...]
 
    private SocketIOOutbound outbound; 
 
    [...]

    @Override 
    public void onConnect(SocketIOOutbound outbound) { 
        this.outbound = outbound; 
        servlet.add(this); 
        servlet.broadcast(user + " connected"); 
    } 
 
    @Override 
    public void onDisconnect(DisconnectReason reason, 
                             String errorMessage) { 
        outbound = null; 
        request.getSession().removeAttribute("user"); 
        servlet.remove(this); 
        servlet.broadcast(user + " disconnected"); 
    } 
 
    @Override 
    public void onMessage(int messageType, String message) { 
        if ("/disconnect".equals(message)) { 
            outbound.close(); 
        } else { 
            servlet.broadcast("[" + user + "] " + message); 
        } 
    } 
 
    void send(String data) { 
        try { 
            if (outbound != null 
    && outbound.getConnectionState() == ConnectionState.CONNECTED) { 
                outbound.sendMessage(data); 
            } 
        } catch (IOException e) { 
            outbound.close(); 
        } 
    } 
 
}

Ví dụ hoàn chỉnh của Socket.IO được đưa vào mã nguồn trong thư mục socketio.


Kết luận

Tất cả các web container đều hỗ trợ Comet và hầu như tất cả chúng đều hỗ trợ WebSockets. Thậm chí nếu các đặc tả dẫn đến một số việc triển khai hiện thực nguyên gốc khác nhau, bạn vẫn có thể phát triển một ứng dụng web bằng cách sử dụng Comet với các API chung (Servlet 3.0 hoặc Jetty Continuations). Và, thậm chí tốt hơn nữa, bạn có thể sử dụng sức mạnh của Comet và WebSockets một cách trong suốt bằng cách sử dụng các thư viện ví dụ như Socket.IO. Hai thư viện bổ sung, Atmosphere và CometD, sẽ được trình bày trong phần tiếp theo của loạt bài này. Tất cả ba thư viện đều được nhiều trình duyệt hỗ trợ, một trải nghiệm người dùng tuyệt vời và nhiều lợi ích về xử lý lỗi, một API dễ dàng hơn, thời gian chờ và các kết nối lại.


Tải về

Mô tảTênKích thước
Article source codereverse_ajaxpt3_source.zip21KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

  • Jetty: Nhận Jetty, một máy chủ web và container javax.servlet, thêm sự hỗ trợ WebSockets.
  • Tài liệu hướng dẫn I/O nâng cao Tomcat của Apache: Nhận các liên kết có giá trị, Hướng dẫn người dùng, tài liệu tham khảo và các chỉ dẫn Phát triển Tomcat của Apache.
  • Framework Grizzly NIO: Giúp bạn tận dụng lợi thế của API Java NIO.
  • Ví dụ về Grizzly Comet: Xem những mà bạn có thể thay đổi được trên ứng dụng hiện có trước khi bắt đầu xây dựng một cái mới.
  • Glassfish Application Server: Nhận ấn bản nguồn mở chính thức của máy chủ GlassFish.
  • Socket.IO Java: Tìm hiểu về dự án của Ovea với những cập nhật mới nhất.
  • Apache Maven: Nhận Maven, một công cụ gộp và quản lý dự án phần mềm.
  • Bộ công cụ phát triển Java, Phiên bản 6: Nhận nền tảng Java, ấn bản chuẩn (Java SE), cho phép bạn phát triển và triển khai các ứng dụng Java trên các máy tính để bàn và các máy chủ, cũng như trong các môi trường nhúng đòi hỏi khắt khe hiện nay.
  • Hãy dùng thử hơn 100 phần mềm IBM miễn phí. Tải về hay đăng nhập vào bản dùng thử trực tuyến, làm việc với sản phẩm trong một môi trường sandbox hoặc truy cập nó thông qua đám mây.

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=855897
ArticleTitle=Reverse Ajax, Phần 3: Các máy chủ Web và Socket.IO
publish-date=01232013