`
redstarofsleep
  • 浏览: 443567 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

基于Tomcat的WebSocket(5月8日更新)

 
阅读更多

2014年2月更新: 此API为Tomcat私有,当时Java没有标准API,现在Java有标准API,JSR536,此API不建议使用,新的用法请参照: http://redstarofsleep.iteye.com/blog/1974620

 

之前大概的看过WebSocket,当时Tomcat还不支持WebSocket,所以当时写了一篇基于Jetty的WebSocket实现,地址如下:

http://redstarofsleep.iteye.com/blog/1307608

 

现在Tomcat7.0.27发布了,从这个版本开始Tomcat就支持WebSocket了。

Tomcat的WebSocket和Jetty的大致上差不多,大同小异,这里就简单的贴两个类吧(此例子未考虑多线程的情况):

 

第一个类,这个和Jetty一样,需要一个Servlet来处理WebSocket请求:

package lhc.websocket;

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

public class MyWebSocketServlet extends WebSocketServlet {

	private static final long serialVersionUID = -7178893327801338294L;

	@Override
	protected StreamInbound createWebSocketInbound(String arg0) {
System.out.println("##########");
		return new MyMessageInbound();
	}

}

这个Servlet继承自WebSocketServlet,实现createWebSocketInbound方法。该方法返回第二个类的实例。

 

第二个类,处理每一次具体的WebSocket任务:

package lhc.websocket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;

import lhc.init.InitServlet;

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

public class MyMessageInbound extends MessageInbound {

	@Override
	protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onTextMessage(CharBuffer msg) throws IOException {
		for (MessageInbound messageInbound : InitServlet.getSocketList()) {
			CharBuffer buffer = CharBuffer.wrap(msg);
			WsOutbound outbound = messageInbound.getWsOutbound();
			outbound.writeTextMessage(buffer);
			outbound.flush();
		}
		
	}

	@Override
	protected void onClose(int status) {
		InitServlet.getSocketList().remove(this);
		super.onClose(status);
	}

	@Override
	protected void onOpen(WsOutbound outbound) {
		super.onOpen(outbound);
		InitServlet.getSocketList().add(this);
	}
	
	

}

 

 这个类继承自MessageInbound类,必须实现onBinaryMessage和onTextMessage方法。Jetty中只有一个onMessage方法,而Tomcat细化成了2个方法。

 

还要一个初始化的Servlet

package lhc.init;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.apache.catalina.websocket.MessageInbound;

public class InitServlet extends HttpServlet {

	private static final long serialVersionUID = -3163557381361759907L;
	
	private static List<MessageInbound> socketList;  
    
    public void init(ServletConfig config) throws ServletException {  
        InitServlet.socketList = new ArrayList<MessageInbound>();  
        super.init(config);  
        System.out.println("Server start============");  
    }  
      
    public static List<MessageInbound> getSocketList() {  
        return InitServlet.socketList;  
    }  
}

 

 

最后,web.xml中进行一下Servlet的配置。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>wsoc</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
  	<servlet-name>mywebsocket</servlet-name>
  	<servlet-class>lhc.websocket.MyWebSocketServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>mywebsocket</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>
  
  <servlet>
  	<servlet-name>initServlet</servlet-name>
  	<servlet-class>lhc.init.InitServlet</servlet-class>
  	<load-on-startup>1</load-on-startup>
  </servlet>
</web-app>

 

 

页面的话,就是标准的HTML5的websocket,这个和服务器是否是Tomcat或者Jetty是无关的:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Index</title>
<script type="text/javascript">
var ws = null;
function startWebSocket() {
	if ('WebSocket' in window)
		ws = new WebSocket("ws://localhost:8080/wsoc/mywebsocket.do");
	else if ('MozWebSocket' in window)
		ws = new MozWebSocket("ws://localhost:8080/wsoc/mywebsocket.do");
	else
		alert("not support");
	
	
	ws.onmessage = function(evt) {
		alert(evt.data);
	};
	
	ws.onclose = function(evt) {
		alert("close");
	};
	
	ws.onopen = function(evt) {
		alert("open");
	};
}

function sendMsg() {
	ws.send(document.getElementById('writeMsg').value);
}
</script>
</head>
<body onload="startWebSocket();">
<input type="text" id="writeMsg"></input>
<input type="button" value="send" onclick="sendMsg()"></input>
</body>
</html>

 

 转载请注明出处

17
0
分享到:
评论
51 楼 redstarofsleep 2012-11-27  
yueool 写道
问个问题,
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest request) {
    // TODO Auto-generated method stub
    return new MyMessageInbound();
}

在SERVLET里override这个方法并返回MessageInbound对象就实现了连接。我的问题是,怎样阻止一个连接。举个例子来说,我希望聊天室里不能超过20人,那么当第21个用户想进来的时候我怎样不让他连接,我尝试过return null。这样就连不上了,但是报了个异常,而且我不清楚我这样写是否标准。想问下应该怎样写最好?


重写doGet方法,在这个方法里做判断,如果满了20人就不调用super.doGet(),这时createWebSocketInbound方法根本不会被调用,也就不会去创建WebSocket了,如果还不满20人,要调用super.doGet();

还有一种方法是先让他连上来,然后再MessageInbound类的onOpen方法里面判断,满了还可以发个消息给这个客户端,然后再调用onClose()方法,强制把这个客户端断开。但是这个onClose()要传一个整型的status参数的,我现在还没有找到该传几回去。。
50 楼 yueool 2012-11-26  
问个问题,
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest request) {
    // TODO Auto-generated method stub
    return new MyMessageInbound();
}

在SERVLET里override这个方法并返回MessageInbound对象就实现了连接。我的问题是,怎样阻止一个连接。举个例子来说,我希望聊天室里不能超过20人,那么当第21个用户想进来的时候我怎样不让他连接,我尝试过return null。这样就连不上了,但是报了个异常,而且我不清楚我这样写是否标准。想问下应该怎样写最好?
49 楼 yueool 2012-11-21  
bin381 写道
你好我想问一下如果得到session呢。我使用login.action在session记录了用户名,那么如何在chat.ws如果取得这个session呢?

博主的代码是在TOMCAT7.0.27下写的,如果你用TOMCAT7.0.32就方便多了
区别在这里 在extends WebSocketServlet时实现了一个方法(7.0.32)
protected StreamInbound createWebSocketInbound(String arg0,HttpServletRequest request) {
// TODO Auto-generated method stub
returnnew MyMessageInbound();;
}

注意,比7.0.27多了一个参数HttpServletRequest request,这个request你就拿去用吧
48 楼 yueool 2012-11-14  
yaolifei 写道
android版的chrome可以 亲测

我用苹果IOS5.1.1系统,safari chrome uc 360 四个浏览器都试过了没有能用的
47 楼 redstarofsleep 2012-11-13  
yaolifei 写道
yueool 写道
搞定了,
1TOMCAT不同版本略语区别
2线程支持可以改用Vector
现在还有最后一个问题,就是为啥手机浏览器不好用,我用苹果的safari不行
UC也不行

android版的chrome可以 亲测

可惜偶的手机Android2.3的,装不了Chrome啊~~~
46 楼 yaolifei 2012-11-13  
yueool 写道
搞定了,
1TOMCAT不同版本略语区别
2线程支持可以改用Vector
现在还有最后一个问题,就是为啥手机浏览器不好用,我用苹果的safari不行
UC也不行

android版的chrome可以 亲测
45 楼 redstarofsleep 2012-11-09  
yueool 写道
搞定了,
1TOMCAT不同版本略语区别
2线程支持可以改用Vector
现在还有最后一个问题,就是为啥手机浏览器不好用,我用苹果的safari不行
UC也不行

之前有试过Android自带的浏览器,也没有试成功。
移动版FF没试过。
44 楼 redstarofsleep 2012-11-09  
redstarofsleep 写道
redstarofsleep 写道
我的意思并不是说这个代码不支持多用户。
InitServlet.socketList = new ArrayList<MessageInbound>();
ArrayList不是线程安全的。当两个线程同时操作这个List的时候,有可能会出问题。


怎么能让他安全呢? 我用数组对象可以不

多线程访问共享资源,用synchronized同步。
43 楼 yueool 2012-11-09  
搞定了,
1TOMCAT不同版本略语区别
2线程支持可以改用Vector
现在还有最后一个问题,就是为啥手机浏览器不好用,我用苹果的safari不行
UC也不行
42 楼 yueool 2012-11-09  
http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html
yaolifei 写道
http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html


翻一下啊
41 楼 yueool 2012-11-09  
手机浏览器不支持??
40 楼 yueool 2012-11-09  
redstarofsleep 写道
我的意思并不是说这个代码不支持多用户。
InitServlet.socketList = new ArrayList<MessageInbound>();
ArrayList不是线程安全的。当两个线程同时操作这个List的时候,有可能会出问题。


怎么能让他安全呢? 我用数组对象可以不
39 楼 yueool 2012-11-09  
基本都搞通了,这篇文章写的很不错
现在准备写个示例型的聊天室
38 楼 yaolifei 2012-11-09  
http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html
37 楼 yaolifei 2012-11-09  
yueool 写道
博主的代码
10.    @Override 
11.    protected StreamInbound createWebSocketInbound(String arg0) {  
12.System.out.println("##########");  
13.        return new MyMessageInbound();  
14.    }

在我的环境里会报错,我改成
@Override
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest arg1) {
// TODO Auto-generated method stub
return new MyMessageInbound();
}
就好了,不知道什么原因, 我用的是TOMCAT7.0.32



tomcat自己都说了:
Tomcat provides support for WebSocket as defined by RFC 6455. This feature is not yet finalised and you are encouraged to provide feedback in the form of bug reports (via Bugzilla), suggested API changes (via the dev list) or other comments (again via the dev list).
36 楼 redstarofsleep 2012-11-09  
redstarofsleep 写道
yueool 写道
找到了,原来有向客户端推送的
        CharBuffer buffer = CharBuffer.wrap("hello,welcome to connect!");
        try {
            this.getWsOutbound().writeTextMessage(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
问题是,这个是当前连接的用户,,我咋么向所有连接的客户端推送消息?


。。。。我这个代码的例子就是向所有在线用户发送消息的,你再看看,你贴的这段外面还有的for循环。

我的意思并不是说这个代码不支持多用户。
InitServlet.socketList = new ArrayList<MessageInbound>();
ArrayList不是线程安全的。当两个线程同时操作这个List的时候,有可能会出问题。
35 楼 yueool 2012-11-09  
博主的代码
10.    @Override 
11.    protected StreamInbound createWebSocketInbound(String arg0) {  
12.System.out.println("##########");  
13.        return new MyMessageInbound();  
14.    }

在我的环境里会报错,我改成
@Override
protected StreamInbound createWebSocketInbound(String arg0, HttpServletRequest arg1) {
// TODO Auto-generated method stub
return new MyMessageInbound();
}
就好了,不知道什么原因, 我用的是TOMCAT7.0.32
34 楼 yueool 2012-11-09  
redstarofsleep 写道
yueool 写道
找到了,原来有向客户端推送的
        CharBuffer buffer = CharBuffer.wrap("hello,welcome to connect!");
        try {
            this.getWsOutbound().writeTextMessage(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
问题是,这个是当前连接的用户,,我咋么向所有连接的客户端推送消息?


。。。。我这个代码的例子就是向所有在线用户发送消息的,你再看看,你贴的这段外面还有的for循环。

抱歉,确实是我看错了,我把另一篇文章的代码看混了。
我还一个问题你在文章中说“Tomcat的WebSocket和Jetty的大致上差不多,大同小异,这里就简单的贴两个类吧(此例子未考虑多线程的情况):”。我想问下,你说的未考虑多线程是什么意思? 然后又说可以向所有在线用户发消息,这里有点不明白请赐教
33 楼 redstarofsleep 2012-11-09  
yueool 写道
找到了,原来有向客户端推送的
        CharBuffer buffer = CharBuffer.wrap("hello,welcome to connect!");
        try {
            this.getWsOutbound().writeTextMessage(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
问题是,这个是当前连接的用户,,我咋么向所有连接的客户端推送消息?


。。。。我这个代码的例子就是向所有在线用户发送消息的,你再看看,你贴的这段外面还有的for循环。
32 楼 redstarofsleep 2012-11-09  
bin381 写道
你好我想问一下如果得到session呢。我使用login.action在session记录了用户名,那么如何在chat.ws如果取得这个session呢?


你试下,这样是不是拿到session了
public class MyWebSocketServlet extends WebSocketServlet {

	private static final long serialVersionUID = -7178893327801338294L;
	
	private HttpSession session;

	@Override
	protected StreamInbound createWebSocketInbound(String arg0) {
System.out.println("##########"+arg0);
		return new MyMessageInbound(this.session);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
System.out.println("@@@@@@@@");

		this.session = req.getSession();
		
		session.setAttribute("user", "userName");

		super.doGet(req, resp);
	}
}


public class MyMessageInbound extends MessageInbound {
	
	private HttpSession session;
	
	public MyMessageInbound(HttpSession session) {
		this.session = session;
	}

	@Override
	protected void onBinaryMessage(ByteBuffer arg0) throws IOException {
		// TODO Auto-generated method stub
		
	}

	@Override
	protected void onTextMessage(CharBuffer msg) throws IOException {
		
System.out.println("=========>" + this.session.getAttribute("user"));
		for (MessageInbound messageInbound : InitServlet.getSocketList()) {
			CharBuffer buffer = CharBuffer.wrap(msg);
			WsOutbound outbound = messageInbound.getWsOutbound();
			outbound.writeTextMessage(buffer);
			outbound.flush();
		}
		
	}

	@Override
	protected void onClose(int status) {
		InitServlet.getSocketList().remove(this);
		super.onClose(status);
	}

	@Override
	protected void onOpen(WsOutbound outbound) {
		super.onOpen(outbound);
		InitServlet.getSocketList().add(this);
	}
}

相关推荐

    Tomcat WebSocket

    8. **集成与部署**:在Tomcat中,WebSocket应用需要正确配置,包括在web.xml中声明WebSocket服务,以及确保使用的WebSocket库(如这里的websocket-api.jar)已经包含在类路径中。 9. **应用示例**:WebSocket广泛...

    java tomcat 7.0.42 websocket可使用

    java tomcat 7.0.42 websocket可使用java tomcat 7.0.42 websocket可使用java tomcat 7.0.42 websocket可使用java tomcat 7.0.42 websocket可使用

    基于Tomcat实现HTML5的WebSocket

    对于Tomcat 8及以上版本,这个步骤通常是不必要的,因为WebSocket已经是默认支持的。 3. **客户端连接** - 在HTML5的JavaScript中,可以使用`WebSocket`对象来建立与服务器的连接。通过`new WebSocket("ws://...

    基于tomcat的websocket开发示例源码

    在这个基于Tomcat的WebSocket开发示例中,我们将深入探讨如何利用WebSocket技术来实现服务器与客户端之间的双向交互。 首先,我们需要确保运行环境满足要求,即Tomcat版本至少为7.0.47。Tomcat从7.0版本开始支持...

    基于Tomcat7、Java、Ext、WebSocket的聊天室

    这个项目是基于Tomcat7、Java、Ext和WebSocket构建的一个聊天室,旨在提供一个交互式的在线交流平台。下面将详细阐述这些技术及其在聊天室中的应用。 **Tomcat7**: Tomcat7是Apache软件基金会的Jakarta项目下的一...

    tomcat7.0.42 下部署websocket需要替换的包

    WebSocket的实现是基于Servlet API的扩展,因此更新这个文件可能包括了WebSocket的实现改进。 6. **tomcat-jdbc.jar**:与`tomcat-dbcp.jar`类似,处理WebSocket应用可能涉及的数据库连接。确保数据库操作的兼容性...

    tomcat8+websocket演示

    tomcat8真正支持jsr-356(包含对websocket的支持), tomcat7部分版本的websocket实现不兼容jsr-356。 需要注意websocket与浏览器的兼容问题,有些早期版本的浏览器支持旧版本的websocket协议,可能会与新版本的...

    websocket+tomcat+jetty+netty

    “tomcatWS-0.0.1-SNAPSHOT.war”看起来是一个基于Tomcat的Web应用程序的WAR(Web Archive)文件。WAR文件是Java Web应用的标准打包格式,包含了所有的静态资源、Servlet类、JSP文件等。在这个例子中,可能包含了...

    tomcat实现websocket.rar

    tomcat实现websocket.rar所需jar包。

    基于Springboot websocket + js实现的即时聊天系统.zip

    基于Springboot websocket + js实现的即时聊天系统 基于Springboot websocket + js实现的即时聊天系统 基于Springboot websocket + js实现的即时聊天系统 基于Springboot websocket + js实现的即时聊天系统 基于...

    tomcat-websocket.jar

    tomcat-websocket.jar

    WebSocket的Java和Tomcat7使用示例

    ### WebSocket的Java和Tomcat7使用详解 #### 一、WebSocket简介 随着互联网技术的不断发展,Web应用变得越来越复杂,传统的HTTP协议已经无法满足实时通信的需求。为了改善这一状况,HTML5引入了WebSocket协议,这...

    基于Springboot+Websocket的简单聊天室

    基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+Websocket的简单聊天室 基于Springboot+...

    支持websocket的tomcat

    支持websocket的tomcat

    使用JSR356在Java中构建WebSocket应用

    使用JSR356在Java中构建WebSocket应用,详细介绍,包括1.服务器推送给客户端和2.客户端发送给服务器

    Tomcat9.0使用WebSocket实现点对点之间的聊天Demo

    WebSocket是HTML5引入的一种在单个TCP连接上进行全双工通信的协议,极大地改进了浏览器与服务器的数据传输效率,特别适用于实时性要求高的应用场景,如在线聊天、游戏、股票交易等。本教程将通过Tomcat 9.0来演示...

    tomcat7-websocket.jar

    tomcat7-websocket.jar

    tomcat-embed-websocket-9.0.16.jar

    tomcat-embed-websocket-9.0.16.jar

Global site tag (gtag.js) - Google Analytics