java websockect
https://github.com/TooTallNate/Java-WebSocket (websockect类库包)
http://blog.openlg.net/index.php/archives/129(实例篇)
http://my.oschina.net/yushulx/blog/298140 (使用Jetty搭建Java Websocket Server,实现图像传输)
http://linxh83.iteye.com/blog/1466017 (jWebSocket使用指南)
http://findhy.com/blog/2014/06/12/java-websocket/(Java-WebSocket)
http://tomcat.apache.org/ (7.0.26支持websocket)
http://java-websocket.org/ (A barebones WebSocket client and server implementation written in 100% Java.)
使用WebSocket技术实现浏览器和服务器的双向通信(一)
WebSocket 规范的目标是在浏览器中实现和服务器端双向通信。双向通信可以拓展浏览器上的应用类型,例如实时的数据推送(股票行情)、游戏、聊天等.
目前在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更好的节省服务器资源和带宽并达到实时通讯。
目录结构:
1.WebSocket Server服务抽象类WSServer.java:
package com.hisense.romeo.websocket.server; /**
*
* WebSocket Server服务抽象类
* 自定义处理WebSocket客户端请求的服务:
* 1.继承并实现此类抽象方法
* 2.修改配置文件/WEB-INF/conf/spring/applicationContext-websocket.xml,给wsServerDispatcher添加处理
* 例如:实现一个简单的聊天室,在配置文件中添加
* {@code
*
* }
* 当客户端请求ws://127.0.0.1:8089/chat时,系统会自动将请求分派给com.hisense.romeo.websocket.server.dispatcher.ChatWSServer处理
* 3.如需发送消息可以直接调用wsServerDispatcher.sendMessage方法
*
*
* @see com.hisense.romeo.websocket.server.IWSServerDispatcher
*
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version v0.0.1
*/
public abstract class WSServer implements IWSServer { /**
* 当前调度WebSocket请求的服务,实现者可以用它进行向客户但发送消息
*/
protected IWSServerDispatcher wsServerDispatcher; /**
* 注册当前WebSocket服务调度员的方法
*
* @param wsServerDispatcher
*/
public void registerWSServerDispatcher(IWSServerDispatcher wsServerDispatcher) {
this.wsServerDispatcher = wsServerDispatcher;
}
}
2.WebSocket请求调度工作WSServerDispatcher.java:
package com.hisense.romeo.websocket.server; import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set; import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.java_websocket.WebSocket;
import org.java_websocket.WebSocketServer;
import org.java_websocket.handshake.ClientHandshake;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; /**
*
* 实现WebSocket请求调度工作
* 根据客户端请求地址中的请求资源进行调度
* 例如:Address: ws://127.0.0.1:8089/chat
* 程序会获取address中的chat进行分发请求。
*
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version
*
*/
public class WSServerDispatcher extends WebSocketServer implements IWSServerDispatcher, InitializingBean, DisposableBean{ /**
* Log4j
*/
private Logger logger = Logger.getLogger(this.getClass()); private Map<string, iwsserver=""> wsServers; private static int port = 8089; public WSServerDispatcher() throws UnknownHostException {
this(new InetSocketAddress(port));
} public WSServerDispatcher(InetSocketAddress address){
super(address);
logger.debug("default using port '" + address.getPort() + "' to startup the WebSocket Server." );
} /**
* 建立新连接时自动调用此方法
*
* @see org.java_websocket.WebSocketServer#onOpen(org.java_websocket.WebSocket, org.java_websocket.handshake.ClientHandshake)
*/
@Override
public void onOpen(WebSocket ws, ClientHandshake clientHandData) {
ws.setHandshakedata(clientHandData);
logger.debug("new Client:\n " + ws.getRemoteSocketAddress() + "\n " + clientHandData.getResourceDescriptor());
} /**
* 当接收到新消息时调用此方法
*
* @see org.java_websocket.WebSocketServer#onMessage(org.java_websocket.WebSocket, java.lang.String)
*/
@Override
public void onMessage(WebSocket ws, String message) {
logger.debug("new Message:\n: " + ws.getRemoteSocketAddress() + ":\n " + message);
String resource = getResourceDescriptor(ws);
if(resource != null && resource.trim().length()!=0){
IWSServer listener = wsServers.get(resource);
if(listener != null)
listener.onMessage(ws, message);
else
logger.error("请求资源" + resource + "不存在!");
} else
logger.error("请求资源不能为空!");
} /**
* 连接关闭时自动调用此方法
*
* @see org.java_websocket.WebSocketServer#onClose(org.java_websocket.WebSocket, int, java.lang.String, boolean)
*/
@Override
public void onClose(WebSocket ws, int arg1, String arg2, boolean arg3) {
logger.debug("client close:\n" + ws.getRemoteSocketAddress());
} /**
* 当连接出现错误时自动调用此方法
*
* @see org.java_websocket.WebSocketServer#onError(org.java_websocket.WebSocket, java.lang.Exception)
*/
@Override
public void onError(WebSocket ws, Exception e) {
logger.error("client error:\n" + ws.getRemoteSocketAddress() + "\n", e);
} /**
* 根据请求资源导航串获取所有的客户端
*
* @param navigation
* @return
*/
@Override
public Set getClientByNavigation(String navigation){
if( navigation == null)
return null; Set wss = new HashSet();
Set conections = this.connections();
for (WebSocket webSocket : conections) {
String resource = this.getResourceDescriptor(webSocket);
if(resource != null && resource.equals(navigation))
wss.add(webSocket);
}
return wss;
} /**
* 获取客户端数量
* @see com.hisense.romeo.websocket.server.IWSSendMessage#getClientCount(java.lang.String)
*/
@Override
public int getClientCount(String name){
Set set = this.getClientByNavigation(name);
if(set != null)
return set.size();
return 0;
} /**
* 给${navigation}的所有客户段发送消息${message}
*
* @param message
* @param navigation Not Null
*/
public void sendMessage(String message, String navigation){
this.sendMessage(this.getClientByNavigation(navigation), message);
} /**
* 发送消息给所有客户端
*
* @param message
*/
public void sendMessageToAll(String message){
this.sendMessage(this.connections(), message);
} /**
* 发送消息给wss
*
* @param wss
* @param message
*/
public void sendMessage(Set wss, String message){
if( wss != null)
for (WebSocket webSocket : wss) {
webSocket.send(message);
}
} /**
* 当服务器退出时调用此方法
*
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
@Override
public void destroy() throws Exception {
logger.info("Stop web socket server...");
super.stop();
if( wsServers != null && !wsServers.isEmpty()){
Set set = wsServers.keySet();
for (String key : set) {
wsServers.get(key).destroy();
}
}
} /**
* 当服务器启动时调用此方法
*
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
logger.info("**Startup web socket server,listening on port <" + port + ">.**"); if(wsServers == null )
wsServers = new HashMap<string, iwsserver="">(); try {
WebSocket.DEBUG = Logger.getLogger("com.hisense.romeo.websocket.server").getLevel().toInt() == Level.DEBUG_INT; this.start(); logger.debug("**Initialization dispatchers.**");
Collection collection = wsServers.values();
for (IWSServer wsServerListener : collection) {
wsServerListener.registerWSServerDispatcher(this);
} logger.info("**WebSocket server has started.**");
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 获取客户端webSocket
请求的资源
*
* @param webSocket
* @return
*/
private String getResourceDescriptor(WebSocket webSocket){
if(webSocket != null && webSocket.getHandshakedata() != null){
String resource = webSocket.getHandshakedata().getResourceDescriptor();
if(resource != null && resource.length() > 0)
return resource.substring(1);
else
return resource;
} else
return null;
} /**
* 设置WebSocket服务的监听端口
*
* @param port
*/
public void setPort(int port) {
WSServerDispatcher.port = port;
this.setAddress(new InetSocketAddress(port));
logger.debug("Update port to '" + port + "' ant startup the WebSocket Server." );
} public int getPort(){
return super.getPort();
} public Map<string, iwsserver=""> getWsServers() {
return wsServers;
} public void setWsServers(Map<string, iwsserver=""> wsServers) {
this.wsServers = wsServers;
} }
3.接口IWSServerDispatcher.java:
package com.hisense.romeo.websocket.server; import java.util.Set; import org.java_websocket.WebSocket; /**
* <pre>
* getClientByNavigation(String navigation) 根据请求资源导航串获取所有的客户端
* sendMessage(String message, String navigation) 给请求${navigation}的所有客户段发送消息${message}
* sendMessage(Set<WebSocket> wss, String message) 发送消息给${wss}
* sendMessageToAll(String message) 发送消息给所有客户端
* </pre>
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version v0.0.1
*
*/
public interface IWSServerDispatcher extends IWSSendMessage{ /**
* 根据请求资源导航串获取所有的客户端
*
* @param navigation
* @return
*/
public Set<WebSocket> getClientByNavigation(String navigation);
}
4.接口IWSServer.java:
package com.hisense.romeo.websocket.server; import org.java_websocket.WebSocket; /**
*
*
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version
*
*/
public interface IWSServer { /**
* 注册当前WebSocket服务调度员的方法
*
* @param wsServerDispatcher
*/
public void registerWSServerDispatcher(IWSServerDispatcher wsServerDispatcher); /**
* 当接收到客户端消息时,会调用这个方法
*
* @param ws 客户端信息
* @param msg 接收到的消息
*/
public abstract void onMessage(WebSocket ws, String msg); /**
* 销毁方法,当服务器停止时调用这个方法
*/
public abstract void destroy();
}
5.接口IWSSendMessage.java:
package com.hisense.romeo.websocket.server; import java.util.Set; import org.java_websocket.WebSocket; /**
* 定义使用WebSocket向客户端发送消息的方法
*
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version
*
*/
public interface IWSSendMessage { /**
* 给请求${navigation}的所有客户段发送消息${message}
*
* @param message 要发送的消息
* @param navigation Not Null
*/
public void sendMessage(String message, String navigation); /**
* 发送消息给<code>wss</code>
*
* @param wss
* @param message
*/
public void sendMessage(Set<WebSocket> wss, String message); /**
* 发送消息给所有客户端
*
* @param message
*/
public void sendMessageToAll(String message); /**
* 根据名字查询客户端数量
*
* @param name
*/
public int getClientCount(String name);
}
6.消息值对象:MessageEntity.java
package com.hisense.romeo.websocket.common; import java.io.Serializable; /**
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version v0.0.1
*
*/
public class MessageEntity implements Serializable{ /**
*
*/
private static final long serialVersionUID = 1L; /**
* 用户名
*/
private String user; /**
* 密码
*/
private String pass; /**
* 目标模块
*/
private String target; /**
* 消息
*/
private String message; /**
* 是否成功
*/
private boolean success = true; public String getUser() {
return user;
} public void setUser(String user) {
this.user = user;
} public String getPass() {
return pass;
} public void setPass(String pass) {
this.pass = pass;
} public String getTarget() {
return target;
} public void setTarget(String target) {
this.target = target;
} public String getMessage() {
return message;
} public void setMessage(String message) {
this.message = message;
} public boolean getSuccess() {
return success;
} public void setSuccess(boolean success) {
this.success = success;
} }
7.业务值对象:RefreshVO.java
package com.hisense.romeo.websocket.common; /**
* <pre>
* 值对象
* 用于WebSocket推送数据变化的进行数据刷新的值对象
* </pre>
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version
*
*/
public class RefreshVO extends MessageEntity { /**
*
*/
private static final long serialVersionUID = 1L; /**
* 变化的表名称
*/
private String[] tables; public String[] getTables() {
return tables;
} public void setTables(String[] tables) {
this.tables = tables;
}
}
8.用于聊天的服务端程序ChatWSServer.java
package com.hisense.romeo.websocket.server.dispatcher; import org.java_websocket.WebSocket; import com.hisense.romeo.websocket.server.WSServer; /**
* 实现简单聊天室
*
* @author lirufei@lg mailto:lirufei0808@gmail.com
* @version
*
*/
public class ChatWSServer extends WSServer{ /**
* @see com.hisense.romeo.websocket.server.IWSServer#onMessage(org.java_websocket.WebSocket, java.lang.String)
*/
@Override
public void onMessage(WebSocket ws, String msg) {
if(wsServerDispatcher != null )
wsServerDispatcher.sendMessage(ws.getRemoteSocketAddress().getHostName() + "说:" + msg, "chat");
} /**
* @see com.hisense.romeo.websocket.server.IWSServer#destroy()
*/
@Override
public void destroy() { } }
9.用于发送和接收消息的客户端代码chat.js:
// Write your code in the same way as for native WebSocket:
var hostname = location.hostname,
ws = new WebSocket('ws://' + hostname + ':8089/chat'),
msg = document.getElementById('msg'),
text = document.getElementById('text'),
btn = document.getElementById('button'); setMsgValue = function(val){
msg.value = msg.value + val;
if(msg.scrollByLines)
msg.scrollByLines(5);
else
msg.scrollTop = msg.value.length;
}; ws.onopen = function() {
setMsgValue('open');
};
ws.onmessage = function(e) {
setMsgValue('\n' + e.data);
};
ws.onclose = function() {
setMsgValue('\n' + 'close');
}; btn.onclick = function(){
ws.send(text.value);
text.value='';
};
text.onkeyup = function(e){
if(/(m|M)(s|S)(i|I)(e|E)/.test(navigator.userAgent))
e = window.event;
if(e.keyCode === 13){
ws.send(text.value);
text.value='';
}
}
java websockect的更多相关文章
- Spark案例分析
一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...
- Java EE HTML5 WebSocket 示例
http://www.oschina.net/translate/java-ee-html5-websocket-example?cmp HTML5给Web浏览器带来了全双工TCP连接websocke ...
- 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题
背景起因: 记起以前的另一次也是关于内存的调优分享下 有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...
- Elasticsearch之java的基本操作一
摘要 接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...
- 论:开发者信仰之“天下IT是一家“(Java .NET篇)
比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...
- 故障重现, JAVA进程内存不够时突然挂掉模拟
背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...
- 死磕内存篇 --- JAVA进程和linux内存间的大小关系
运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...
- 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用
有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...
- Java多线程基础学习(二)
9. 线程安全/共享变量——同步 当多个线程用到同一个变量时,在修改值时存在同时修改的可能性,而此时该变量只能被赋值一次.这就会导致出现“线程安全”问题,这个被多个线程共用的变量称之为“共享变量”. ...
随机推荐
- 常用sql笔记
Student(S#,Sname,Sage,Ssex) 学生表Course(C#,Cname,T#) 课程表SC(S#,C#,score) 成绩表Teacher(T#,Tname) 教师表问题:1.查 ...
- 精通 Oracle+Python,第 3 部分:数据解析
进行数据解析的理由不计其数,相关的工具和技巧也同样如此.但是,当您需要用这些数据做一些新的事情时,即使有“合适的”工具可能也是不够的.这一担心对于异类数据源的集成同样存在.用来做这项工作的合适工具迟早 ...
- uboot的mtd功能支持
一.概述 1.MTD MTD是Flash的一种管理方法,将Flash划分成几个分区,便于管理. u-boot的MTD功能是在文件cmd_jffs2.c中实现的,由此我们可以知道怎样打开u-boot的M ...
- C++中Reference与指针(Pointer)的使用对比
整理日: 2015年3月18日 引用(reference)和指针(pointer)是学C++过程中最令人头疼的问题,常常不知道什么时候用哪个合适,又常常弄混.找到Dan Saks的这篇文章,讲的很清楚 ...
- java项目创建和部署
http://www.cnblogs.com/nexiyi/archive/2012/12/28/2837560.html http://dead-knight.iteye.com/blog/1841 ...
- JavaWeb 文件上传 commons_fileupload方式
import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadExcept ...
- Linux Eclipse代码提示功能设置(Java & C/C++)
最近在Linux下开发,由于长期使用Visual Studio 2010,对代码提示功能情有独钟,现在在Linux下,使用Eclipse做开发,当然免不了怀念Visual Studio强悍的代码提示, ...
- HTML Meta, http-equiv, Refresh
原文: http://www.lifelaf.com/blog/?p=481 在HTML页面中,如果想实现定时刷新或重定向,我们可以使用meta标签的refresh功能: <!-- 5秒后刷新页 ...
- [MIREX] MIREX评测介绍
MIREX作为国际最权威音频检索评测大赛,竟然在百度上找不到任何介绍,只有几个与什么搜狗.腾讯获得什么成绩相关的检索内容,相比而言,TRECVID的内容收到重视多了...由于研究生阶段主要研究音频领域 ...
- 《A First Course in Probability》-chaper7-极限定理-强大数定理
在现实问题中我们对于一个实验往往会重复成千上万次,那么我们就需要关注在实验次数趋于无穷之后,整个实验的期望会趋于怎样一个结果.其实这一章“极限定理”都是在处理这个问题. 强大数定理: 这里的证明过程给 ...