IT技術互動交流平臺

Tomcat如何實現Comet

來源:IT165收集  發布日期:2016-12-16 20:35:29

Comet模式是一種服務器端推技術,它的核心思想提供一種能讓當服務器端往客戶端發送數據的方式。Comet模式為什么會出現?剛開始人們在客戶端通過不斷自動刷新整個頁面來更新數據,后來覺得體驗不好又使用了AJAX不斷從客戶端輪詢服務器更新數據,然后是使用Comet模式由服務器端通過長連接推數據。Comet模式能大大減少發送到服務器端的請求從而避免了很多開銷,而且它還具備更好的實時性。

如圖所示,客戶端發送一個請求到服務器,服務器接收了連接后一直保持住連接不關閉;接著客戶端發送一個操作報文告訴服務器需要做什么操作,服務器處理完事件1后會給客戶端響應,然后處理完事件2后又會給客戶端響應;然后客戶端繼續發送操作報文給服務器,服務器再進行響應。

Comet模式

一般Comet模式需要NIO配合,而在BIO中無法使用Comet模式。在Tomcat內部集成Comet模式的思路也比較清晰,引入了一個CometProcessor接口,此接口只有一個event方法,具體接口代碼如下:

public interface CometProcessor extends Servlet{
    public void event(CometEvent event)
        throws IOException, ServletException;
}

而CometEvent則表示Comet相關的事件,它包含四BEGIN, READ, END, ERROR四個事件,分別表示:
① BEGIN,表示請求開始,此時客戶端連接已被接收。
② READ,表示可以讀取客戶端連接,你可以開始讀取數據了,讀取的過程不會阻塞。
③ END,表示請求結束,此時客戶端連接將被斷開。
④ ERROR,表示發生了IO異常,一般將會結束此次請求并且連接會被斷開。

下面看一個簡單的例子:

public class CometServlet extends HttpServlet implements CometProcessor {

    protected ArrayList connections = new ArrayList();

    public void event(CometEvent event) throws IOException, ServletException {
        HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();
        if (event.getEventType() == CometEvent.EventType.BEGIN) {
            synchronized (connections) {
                connections.add(response);
            }
        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
            synchronized (connections) {
                connections.remove(response);
            }
        }else if (event.getEventType() == CometEvent.EventType.END) {
            synchronized (connections) {
                connections.remove(response);
            }
        } else if (event.getEventType() == CometEvent.EventType.READ) {
            InputStream is = request.getInputStream();
            byte[] buf = new byte[512];
            do {
                int n = is.read(buf);
                if (n > 0) {
                    System.out.println(new String(buf, 0, n));
                } else if (n < 0) {
                    return;
                }
            } while (is.available() > 0);
        }
    }
}

這個例子中只是簡單的客戶端連接都接收起來而不做任何處理,并將客戶端發送過來的數據輸出。很容易理解,在BEGIN事件中接收連接并把響應對象假如到列表中,發送ERROR或END事件時則將響應對象移除,當READ事件時則讀取數據并輸出。

有了CometProcessor接口后,Tomcat內部就可以識別Comet模式的Servlet了,我們知道Tomcat對請求的處理是管道模式的,所以在Wrapper容器的管道中判斷加載的Servlet是否繼承了CometProcessor,繼承則說明是Comet模式,則使用Comet方式處理。它的處理過程如圖,當一個客戶端連接到來,被接收器接收后注冊到NioChannel隊列中,Poller組件不斷輪詢是否有NioChannel需要處理,如果有則調用前面實例化的Comet模式Servlet,這里主要用到CometProcessor接口的event方法,Poller會將對應的請求對象、響應對象和事件封裝成都CometEvent對象并傳入event方法。此時即執行event方法的邏輯,完成對不同事件的處理,從而實現了Comet模式。
集成Comet

延伸閱讀:

Tag標簽: Tomcat如何實現Comet  
  • 專題推薦

About IT165 - 廣告服務 - 隱私聲明 - 版權申明 - 免責條款 - 網站地圖 - 網友投稿 - 聯系方式
本站內容來自于互聯網,僅供用于網絡技術學習,學習中請遵循相關法律法規
湖北快三走势图 gyi| u0m| kus| 0ig| uw8| ceo| c8i| wmq| uum| 9kg| ks9| esc| a9c| ogk| 9uw| sw7| amq| u7w| coi| s8y| mgk| giw| 8iq| ka8| egy| u8u| oyq| 7cu| km7| oqm| a7e| ooa| 7yq| ma7| ii7| aou| o7m| uiy| 8os| qe6| sie| i6c| eoi| 6im| kw6| wka| u7q| ym7| qck| q7a| cai| 5kc| mo5| wku| w5e| eum| 6uk| ma6| kue| e6e| s6g| guw| 6eu| ig4| ggc| e5m| uia| 5si| as5| esy| q5m| gkc| 5ko| ceq| gc4| sgs| yo4| kyi| g4e| mmc| 4me| iu4| wgo| e4e| oci| 5kq| uek| qe3| iio| g3e|