基于Tomcat7.0.29的WebSocket實現

jopen 13年前發布 | 94K 次閱讀 Tomcat7 Tomcat 應用服務器

看HTML5的WebSocket的時候在Tomcat7.0.27上寫WebSocket遇到了一個超時的問題,當時調試了一下Tomcat的源碼,確認是底層使用的Socket設置了讀超時的問題,只好放著不管,用Node.js搞了一個測試過去。

現在Tomcat版本換成7.0.29了,看Change Log,超時的問題貌似在7.0.28上解決了,重新把書上的echo.ws重新改成Tomcat版本的,功能很簡單,就是網頁上發什么文本,服務器就回什么文本。

53074: Switch to an infinite socket timeout by default for WebSocket connections. (markt)
服務器端程序需要用到關鍵是WebSocketServlet和MessageInbound,需要注意的是 WebSocketServlet 的createWebSocketInbound方法相對于7.0.27版本多了一個 HttpServletRequest參數(看文檔上說的應該是7.0.28改的)
package fox.web.servlet;

import java.io.IOException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.util.logging.Logger;

import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.MessageInbound; import org.apache.catalina.websocket.StreamInbound; import org.apache.catalina.websocket.WebSocketServlet; import org.apache.catalina.websocket.WsOutbound;

@WebServlet(urlPatterns = "/echo.ws") // 處理WebSocket的Servlet需要繼承自WebSocketServlet,這一點和7.0.27仍然一樣 public class EchoServlet extends WebSocketServlet { // Log private Logger logger = Logger.getLogger(EchoServlet.class.getName());

@Override
// 與7.0.27不同的,Tomcat改變了createWebSocketInbound方法的定義,增加了一個HttpServletRequest參數
// 這樣我們也可以從request參數中獲取更多請求方的信息
protected StreamInbound createWebSocketInbound(String subProtocol,
        HttpServletRequest request) {
    // Log
    logger.info("request ws servlet");

    // 方法仍然是返回一個StreamInbound實例,這里采用實現他的子類MessageInbound
    // 只用實現下面四個事件處理函數(其實onClose和onOpen有缺省實現)
    return new MessageInbound() {
        // WebSocket關閉事件,參數status應該來自org.apache.catalina.websocket.Constants中定義的幾個常量,可以參考文檔或者核對一下Tomcat的源碼
        @Override
        protected void onClose(int status) {
            // Log
            logger.info("Web Socket Closed: " + status);
        }

        // WebSocket握手完成,創建完畢,WsOutbound用于向客戶端發送數據
        @Override
        protected void onOpen(WsOutbound outbound) {
            // Log
            logger.info("Web Socket Open!");
        }

        // 有二進制消息數據到達,暫時沒研究出這個函數什么情況下觸發,js的WebSocket按理說應該只能send文本信息才對
        @Override
        protected void onBinaryMessage(ByteBuffer buffer)
                throws IOException {
            // Log
            logger.info("Binary Message Receive: " + buffer.remaining());
            // Nothing
        }

        // 有文本消息數據到達
        @Override
        protected void onTextMessage(CharBuffer buffer) throws IOException {
            // Log
            logger.info("Text Message Receive: " + buffer.remaining());
            // getWsOutbound可以返回當前的WsOutbound,通過他向客戶端回傳數據,這里采用的是nio的CharBuffer
            getWsOutbound().writeTextMessage(buffer);
        }
    };
}

}</pre>然后是ws.html上的JavaScript腳本,這個還是照舊了。

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ";
<html> 
    <head> 
        <title>Web Socket Demo</title> 
        <script type="text/javascript"> 
        var ws = null;

    function startServer() {
        // 設定WebSocket,注意協議是ws,請求是指向對應的WebSocketServlet的
        var url = "ws://127.0.0.1:8080/j2ee6/echo.ws";
        // 創建WebSocket實例,下面那個MozWebSocket是Firefox的實現
        if ('WebSocket' in window) { 
            ws = new WebSocket(url);
        } else if ('MozWebSocket' in window) { 
            ws = new MozWebSocket(url); 
        } else { 
            alert('Unsupported.'); 
            return; 
        }

        // WebSocket握手完成,連接成功的回調
        // 有個疑問,按理說new WebSocket的時候就會開始連接了,如果在設置onopen以前連接成功,是否還會觸發這個回調
        ws.onopen = function() { 
            alert('Opened!'); 
        };

        // 收到服務器發送的文本消息, event.data表示文本內容
        ws.onmessage = function(event) { 
            alert('Receive message: ' + event.data); 
        };

        // 關閉WebSocket的回調
        ws.onclose = function() {
            alert('Closed!'); 
        };
    }

    function sendMyMessage() {
        var textMessage = document.getElementById('textMessage').value;

        if(ws != null && textMessage != '') {
            // 通過WebSocket想向服務器發送一個文本信息
            ws.send(textMessage);
        }
    }
    </script>
</head>
<body onload="startServer()"> 
    <input type="text" id="textMessage" size="20" />
    <input type="button" onclick="sendMyMessage()" value="Send">
</body> 

</html> </pre>在Tomcat7.0.29上執行成功。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!