`
redstarofsleep
  • 浏览: 444535 次
  • 性别: 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
分享到:
评论
31 楼 yueool 2012-11-08  
找到了,原来有向客户端推送的
        CharBuffer buffer = CharBuffer.wrap("hello,welcome to connect!");
        try {
            this.getWsOutbound().writeTextMessage(buffer);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
问题是,这个是当前连接的用户,,我咋么向所有连接的客户端推送消息?
30 楼 yueool 2012-11-08  
代码不错,就是楼主没有给出服务器反过来向浏览器推送消息的例子,能否给下
29 楼 yaolifei 2012-11-08  
scut_wangjeff 写道
redstarofsleep 写道
scut_wangjeff 写道
之前运行还好好的  现在不知道为什么一运行tomcat就会抛异常!!
严重: End event threw exception
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

严重: Parse error in application web.xml file at jndi:/localhost/WebTest/WEB-INF/web.xml
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

是不是tomcat的问题还是?


应该不是代码的问题,Tomcat或者是包的问题


网上找过是因为catalina.jar冲突了,说要删掉。但是代码需要调用到包里的类~~你没遇到这问题?

你如果用的maven需要把引用的tomcat的lib设置为provided
28 楼 bin381 2012-11-07  
你好我想问一下如果得到session呢。我使用login.action在session记录了用户名,那么如何在chat.ws如果取得这个session呢?
27 楼 scut_wangjeff 2012-07-25  
redstarofsleep 写道
scut_wangjeff 写道
之前运行还好好的  现在不知道为什么一运行tomcat就会抛异常!!
严重: End event threw exception
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

严重: Parse error in application web.xml file at jndi:/localhost/WebTest/WEB-INF/web.xml
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

是不是tomcat的问题还是?


应该不是代码的问题,Tomcat或者是包的问题


网上找过是因为catalina.jar冲突了,说要删掉。但是代码需要调用到包里的类~~你没遇到这问题?
26 楼 redstarofsleep 2012-07-25  
scut_wangjeff 写道
之前运行还好好的  现在不知道为什么一运行tomcat就会抛异常!!
严重: End event threw exception
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

严重: Parse error in application web.xml file at jndi:/localhost/WebTest/WEB-INF/web.xml
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

是不是tomcat的问题还是?


应该不是代码的问题,Tomcat或者是包的问题
25 楼 scut_wangjeff 2012-07-24  
之前运行还好好的  现在不知道为什么一运行tomcat就会抛异常!!
严重: End event threw exception
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

严重: Parse error in application web.xml file at jndi:/localhost/WebTest/WEB-INF/web.xml
java.lang.NoSuchMethodException: org.apache.catalina.deploy.WebXml addServlet

是不是tomcat的问题还是?
24 楼 redstarofsleep 2012-07-18  
yaolifei 写道
scut_wangjeff 写道
如果我不希望把信息发给自己那应该怎么改??这样是区分不了信息是哪个客户端传进来的。

就像楼主的代码,可以在:
@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 onTextMessage(CharBuffer msg) throws IOException {  
        for (MessageInbound messageInbound : InitServlet.getSocketList()) {
            [b]if (messageInbound == this) 
                continue;[/b]  
            CharBuffer buffer = CharBuffer.wrap(msg);  
            WsOutbound outbound = messageInbound.getWsOutbound();  
            outbound.writeTextMessage(buffer);  
            outbound.flush();  
        }  
          
    }  


或者在自己定义MyMessageInbound时加入用户信息

public class MyMessageInbound extends MessageInbound { 
    private int userId; // 标识是那个用户的
    public MyMessageInbound(int userId){
        this.userId = userId;
    }
}


创建的时候从Session里面获取当前用户信息,向客户端写的时候只要判断一下就可以

恩,说的对,这样可以
23 楼 yaolifei 2012-07-18  
scut_wangjeff 写道
如果我不希望把信息发给自己那应该怎么改??这样是区分不了信息是哪个客户端传进来的。

就像楼主的代码,可以在:
@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 onTextMessage(CharBuffer msg) throws IOException {  
        for (MessageInbound messageInbound : InitServlet.getSocketList()) {
            [b]if (messageInbound == this) 
                continue;[/b]  
            CharBuffer buffer = CharBuffer.wrap(msg);  
            WsOutbound outbound = messageInbound.getWsOutbound();  
            outbound.writeTextMessage(buffer);  
            outbound.flush();  
        }  
          
    }  


或者在自己定义MyMessageInbound时加入用户信息

public class MyMessageInbound extends MessageInbound { 
    private int userId; // 标识是那个用户的
    public MyMessageInbound(int userId){
        this.userId = userId;
    }
}


创建的时候从Session里面获取当前用户信息,向客户端写的时候只要判断一下就可以
22 楼 scut_wangjeff 2012-07-17  
如果我不希望把信息发给自己那应该怎么改??这样是区分不了信息是哪个客户端传进来的。
21 楼 jxfsuda 2012-06-15  
做了浏览器兼容性的示例代码发在这里了

http://www.cnblogs.com/jifsu/archive/2012/06/15/2550603.html

用到的是flash.还需要另外开socket,有点麻烦.
20 楼 jxfsuda 2012-06-15  
yaolifei 写道
jxfsuda 写道
pch272215690 写道
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?

我也遇到这种问题,不知何解。。。。


heartbeat

请问你验证过吗,在js处发心跳?

我也是在js处发心跳包了,大概20秒左右,不发送的话,就会断开.
而且发现个问题:
我的站点的session,如果在websocket这个servlet中也去getSession的话,会把整站的session重新重置. 也就是说,websocket中获取到不到站点中的session,cookie?


看了tomcat的bug list,
https://issues.apache.org/bugzilla/show_bug.cgi?id=53074
上面说trunk版本中已经解决了,所以就下了源代码进行编译,经测试已解决。不知道怎么贴附件,贴上网盘地址,我编译出的版本,暂且为7.0.28版本吧:http://115.com/file/an34jocc#apache-tomcat-7.0.28.rar

谢过兄台!~~
19 楼 yaolifei 2012-06-14  
jxfsuda 写道
pch272215690 写道
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?

我也遇到这种问题,不知何解。。。。


heartbeat

请问你验证过吗,在js处发心跳?

我也是在js处发心跳包了,大概20秒左右,不发送的话,就会断开.
而且发现个问题:
我的站点的session,如果在websocket这个servlet中也去getSession的话,会把整站的session重新重置. 也就是说,websocket中获取到不到站点中的session,cookie?


看了tomcat的bug list,
https://issues.apache.org/bugzilla/show_bug.cgi?id=53074
上面说trunk版本中已经解决了,所以就下了源代码进行编译,经测试已解决。不知道怎么贴附件,贴上网盘地址,我编译出的版本,暂且为7.0.28版本吧:http://115.com/file/an34jocc#apache-tomcat-7.0.28.rar
18 楼 jxfsuda 2012-06-14  
pch272215690 写道
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?

我也遇到这种问题,不知何解。。。。


heartbeat

请问你验证过吗,在js处发心跳?

我也是在js处发心跳包了,大概20秒左右,不发送的话,就会断开.
而且发现个问题:
我的站点的session,如果在websocket这个servlet中也去getSession的话,会把整站的session重新重置. 也就是说,websocket中获取到不到站点中的session,cookie?
17 楼 pch272215690 2012-06-13  
ffyy_0106 写道
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?

我也遇到这种问题,不知何解。。。。


heartbeat

请问你验证过吗,在js处发心跳?
16 楼 ffyy_0106 2012-06-10  
pch272215690 写道
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?

我也遇到这种问题,不知何解。。。。


heartbeat
15 楼 pch272215690 2012-05-17  
wlyfls 写道
请问lz,连接在空闲一断时间后自动终止怎么办?

我也遇到这种问题,不知何解。。。。
14 楼 wlyfls 2012-05-10  
请问lz,连接在空闲一断时间后自动终止怎么办?
13 楼 redstarofsleep 2012-05-08  
junes_yu 写道
redstarofsleep 写道

这个你看上一篇基于Jetty的.那个时候写的是多客户端的.只要定义一个全局的List就可以了:
private static List<MyWebSocket> socketList;换成Tomcat应该是一样的.

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


我已经有一个全局的List用来存放客户端了,但好像还是不行耶~请问如果有时间的话能做个简单的实例分享一下吗?谢谢...


我已经更新过了,你在看看!
12 楼 junes_yu 2012-04-29  
redstarofsleep 写道

这个你看上一篇基于Jetty的.那个时候写的是多客户端的.只要定义一个全局的List就可以了:
private static List<MyWebSocket> socketList;换成Tomcat应该是一样的.

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


我已经有一个全局的List用来存放客户端了,但好像还是不行耶~请问如果有时间的话能做个简单的实例分享一下吗?谢谢...

相关推荐

    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+...

    tomcat-embed-websocket-9.0.16.jar

    tomcat-embed-websocket-9.0.16.jar

    支持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

Global site tag (gtag.js) - Google Analytics