tomcat7之websocket
- - ITeye博客从tomcat7.0.26之后开始支持websocket,建议大家使用tomcat7.0.30,期间版本的接口有一些改动. chrome默认支持websocket. 其他浏览器可能由于安全原因,默认是关闭的. // 与7.0.27不同的,Tomcat改变了createWebSocketInbound方法的定义,增加了一个HttpServletRequest参数.
package com.panguso.phl.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; /** * * @author piaohailin * 2012-09-08 * */ @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.setLevel(java.util.logging.Level.ALL); 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); //模拟服务器通知浏览器,从浏览器就会看,每3秒收到1条服务器消息 // for (int i = 0; i < 3; i++) { // try { // Thread.sleep(3000); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // getWsOutbound().writeTextMessage(CharBuffer.wrap(String.valueOf(i).subSequence(0, 1))); // } } }; } }
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> var ws = null; function startServer() { // 设定WebSocket,注意协议是ws,请求是指向对应的WebSocketServlet的 var url = "ws://127.0.0.1:8080/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> <body onload="startServer()"> <input type="text" id="textMessage" size="20" /> <input type="button" onclick="sendMyMessage()" value="Send"> </body> </html>