HTML5通讯协议——WebSocket
1.导入maven依赖
<!-- websocket -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-websocket</artifactId>
<version>${spring.version}</version>
</dependency> <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-messaging</artifactId>
<version>${spring.version}</version>
</dependency>
2.创建类 HandshakeInterceptor 继承 HttpSessionHandshakeInterceptor
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Map<String, Object> attributes) throws Exception {
/**
* 在拦截器内强行修改websocket协议,将部分浏览器不支持的 x-webkit-deflate-frame 扩展修改成
* permessage-deflate
*/
if (request.getHeaders().containsKey("Sec-WebSocket-Extensions")) {
request.getHeaders().set("Sec-WebSocket-Extensions", "permessage-deflate");
}
String jspCode = ((ServletServerHttpRequest) request).getServletRequest().getParameter("jspCode");
if (jspCode != null) {
attributes.put("jspCode", jspCode);
} else {
return false;
}
return true;
}
@Override
public void afterHandshake(ServerHttpRequest request,
ServerHttpResponse response, WebSocketHandler wsHandler,
Exception ex) {
super.afterHandshake(request, response, wsHandler, ex);
}
}
3.创建类 MyWebSocketConfig 继承 WebMvcConfigurerAdapter 并实现 WebSocketConfigurer
@Component
@EnableWebMvc
@EnableWebSocket
public class MyWebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer {
@Resource
MyWebSocketHandler handler; @Override
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
// TODO Auto-generated method stub
registry.addHandler(handler, "/websocket").addInterceptors(new HandshakeInterceptor());
registry.addHandler(handler, "/websocket/sockjs").addInterceptors(new HandshakeInterceptor()).withSockJS();
}
}
4.创建类 MyWebSocketHandler 实现 WebSocketHandler
@Component
public class MyWebSocketHandler implements WebSocketHandler { public static final Map<String, WebSocketSession> userSocketSessionMap; static {
userSocketSessionMap = new HashMap<String, WebSocketSession>();
} @Override
public void afterConnectionEstablished(WebSocketSession session)
throws Exception {
// TODO Auto-generated method stub
String jspCode = session.getId() + "-" + (String) session.getHandshakeAttributes().get("jspCode"); if (userSocketSessionMap.get(jspCode) == null) {
System.out.println("添加会话:" + jspCode);
userSocketSessionMap.put(jspCode, session);
}
} @Override
public void handleMessage(WebSocketSession session,
WebSocketMessage<?> message) throws Exception {
// TODO Auto-generated method stub
session.sendMessage(message);
} @Override
public void handleTransportError(WebSocketSession session,
Throwable exception) throws Exception {
// TODO Auto-generated method stub
if (session.isOpen()) {
session.close();
}
Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
// 移除Socket会话
while (it.hasNext()) {
Entry<String, WebSocketSession> entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID:" + entry.getKey());
break;
}
}
} @Override
public void afterConnectionClosed(WebSocketSession session,
CloseStatus closeStatus) throws Exception {
// TODO Auto-generated method stub
System.out.println("Websocket:" + session.getId() + "已经关闭");
Iterator<Entry<String, WebSocketSession>> it = userSocketSessionMap.entrySet().iterator();
// 移除Socket会话
while (it.hasNext()) {
Entry<String, WebSocketSession> entry = it.next();
if (entry.getValue().getId().equals(session.getId())) {
userSocketSessionMap.remove(entry.getKey());
System.out.println("Socket会话已经移除:用户ID:" + entry.getKey());
break;
}
}
} @Override
public boolean supportsPartialMessages() {
// TODO Auto-generated method stub
return false;
}
}
5.前段使用
<!-- websocket -->
<script type="text/javascript">
$(function() { var jspCode = "${user.userId}"; var websocket;
if ('WebSocket' in window) {
websocket = new WebSocket("ws://localhost:8080/ebcrawler/websocket?jspCode=" + jspCode);
} else if ('MozWebSocket' in window) {
websocket = new MozWebSocket("ws://localhost:8080/ebcrawler/websocket?jspCode=" + jspCode);
} else {
websocket = new SockJS("http://localhost:8080/ebcrawler/websocket/sockjs?jspCode=" + jspCode);
} websocket.onopen = function(event) {
$(".commonMsg").each(function() {
$(this).html($(this).html() + "已连接<br/>")
});
};
websocket.onmessage = function(event) {
var data = event.data;
var type = data.substring(0, data.indexOf("-"));
var msg = data.substring(data.indexOf("-") + 1);
if (type == "1") {
$("#doneMsg").html($("#doneMsg").html() + msg + "<br/>");
} else if (type == "2") {
$("#doingMsg").html(msg + "<br/>");
} else if (type == "3") {
$("#errorMsg").html(msg + "<br/>" + $("#errorMsg").html());
} else { } };
websocket.onerror = function(event) {
$(".commonMsg").each(function() {
$(this).html($(this).html() + "websocket发生错误<br/>")
});
};
websocket.onclose = function(event) {
$(".commonMsg").each(function() {
$(this).html($(this).html() + "已关闭<br/>")
});
};
});
</script>
6.后端使用
//websocket发给前端
Iterator<Entry<String, WebSocketSession>> it = MyWebSocketHandler.userSocketSessionMap.entrySet().iterator();
// 发给同一userId的客户端
while (it.hasNext()) { final Entry<String, WebSocketSession> entry = it.next();
String keyUserId = entry.getKey().substring(entry.getKey().indexOf("-") + 1);
WebSocketSession session = entry.getValue();
if (session.isOpen() && keyUserId.equals(userId)) {
try {
if (session.isOpen()) {
synchronized(session) {
entry.getValue().sendMessage(new TextMessage(msg));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:当多线程发送消息时,同一个WebSocketSession一次只能发送条消息,所以需要用synchronize将session锁住
HTML5通讯协议——WebSocket的更多相关文章
- websocket通讯协议(10版本)简介
前言: 工作中用到了websocket 协议10版本的,英文的协议请看这里: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotoc ...
- WebSocke实时通讯协议
WebSocket 是什么? WebSocket 是一种网络通信协议.RFC6455 定义了它的通信标准. WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议 ...
- 带你认识HTML5中的WebSocket
这篇文章主要介绍了带你认识HTML5中的WebSocket,本文讲解了HTML5 中的 WebSocket API 是个什么东东.HTML5 中的 WebSocket API 的用法.带Socket. ...
- HTML5新特性 websocket(重点)--多对多聊天室
一.html5新特性 websocket(重点)--多对多聊天室 HTTP:超文本传输协议 HTTP作用:传输网页中资源(html;css;js;image;video;..) HTTP是浏览器搬运 ...
- 基于dubbo框架下的RPC通讯协议性能测试
一.前言 Dubbo RPC服务框架支持丰富的传输协议.序列化方式等通讯相关的配置和扩展.dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC ...
- MODBUS-RTU通讯协议简介
MODBUS-RTU通讯协议简介 什么是MODBUS? MODBUS 是MODICON公司最先倡导的一种软的通讯规约,经过大多数公司 的实际应用,逐渐被认可,成为一种标准的通讯规约,只要按照这种规 ...
- 【读书笔记】iOS-防止通讯协议被轻易破解的方法
开发者可以选择类似Protobuf之类的二进制通讯协议或者自己实现通讯协议,对于传输的内容进行一定程度的加密,以增加黑客破解协议的难度. 参考资料: <iOS开发进阶> --唐巧
- CNN 美国有线电视新闻网 wapCNN WAP 指无线应用通讯协议 ---- 美国有线电视新闻网 的无线应用
wapCNN wap指无线应用通讯协议 CNN美国有线电视新闻网 固, wapCNN 美国有线电视新闻网的无线应用 -------------------------------------- ...
- Netty 对通讯协议结构设计的启发和总结
Netty 通讯协议结构设计的总结 key words: 通信,协议,结构设计,netty,解码器,LengthFieldBasedFrameDecoder 原创 包含与机器/设备的通讯协议结构的设计 ...
随机推荐
- ArcGis dbf读写——挂接Excel到属性表 C#
ArcMap提供了挂接Excel表格信息到属性表的功能,但是当数据量较大到以万计甚至十万计的时候这个功能就歇菜了,当然,你可以考虑分段挂接.这个挂接功能只是做了一个表关联,属性记录每个字段的信息需要通 ...
- VMware Workstation 常见问题解决
本文以FAQ的方式进行整理,大家可以根据关键字进行查找即可. 问题一:VMware 安装64位操作系统报错“此主机支持Intel VT-x, 但Intel VT-x处于禁用状态” 问题二:This v ...
- Laravel框架中打印sql
在使用Laravel框架的时候,调试的时候,需要将查询的SQL输出校验,这是需要将SQL打印出来. 一.方法 DB::connection()->enableQueryLog(); // 开 ...
- HttpUtility.UrlEncode()关于空格的编码问题
因为 HttpUtility.UrlEncode 在 Encode 的时候, 将空格转换成加号"+", 在 Decode 的时候将"+"号转为空格, 但是浏览器 ...
- SqlServer如何获取存储过程的返回值
1.Output参数返回值 1 CREATE PROCEDURE [dbo].[upInformation]( 2 @age int , 3 @id bigint OUTPUT 4 ) 5 AS 6 ...
- iTOP-4412/4418/6818开发板-fastboot烧写脚本
在 iTOP-4412,4418,6818 开发板烧写的时候,使用的是 fastboot 工具. fastboot 工具需要在 cmd.exe 中调用,每次都需要输入烧写命令,这样步骤有点多.在程序员 ...
- Python自动化中的鼠标事件
1)form selenium.webdriver.common.action_chains import ActionChains 导入该模块 2)ActionChains(driver) :用于 ...
- dubbo注册中心
官方推荐的是zookeeper注册中心. 1.Multicast 注册中心 Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现. 提供方启动时广播自己的地址消费方启动 ...
- 机器学习基石7-The VC Dimension
注: 文章中所有的图片均来自台湾大学林轩田<机器学习基石>课程. 笔记原作者:红色石头 微信公众号:AI有道 前几节课着重介绍了机器能够学习的条件并做了详细的推导和解释.机器能够学习必须满 ...
- pointer-events属性屏蔽鼠标事件(点击穿透上层元素)
应用场景 我们在 HTML 开发时可能会遇到这样的情况:页面上有一些元素使用绝对定位布局,这些元素可能会遮盖住它们位置下方的某个元素的部分或者全部.默认情况下,下方元素被遮挡的部分是不会响应鼠标事件的 ...