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 原创 包含与机器/设备的通讯协议结构的设计 ...
随机推荐
- 快速掌握Nginx(二) —— Nginx的Location和Rewrite
1 location详解 1.location匹配规则 Nginx中location的作用是根据Url来决定怎么处理用户请求(转发请求给其他服务器处理或者查找本地文件进行处理).location支持正 ...
- vue+element 正则表达式进行表单验证
<template> <el-form :model="form" label-width="115px" ref="form&qu ...
- 四五月份:关键词是沟通、绘画和SQL
例行总结一下四五月份的感受. 关键词有三个:沟通.绘画和SQL. 整体来说,这两个月在努力跟这三个关键词死磕,略有些进展,因此汇报一下. 虽然这三个关键词从重要度来说是从左到右的,但从叙述来讲,还是先 ...
- 基于Gecko内核的简单浏览器实现
分享一个基于Gecko内核的简单浏览器实现过程. 项目需要需要开发一个简单浏览器,由于被访问的网页中有大量Apng做的动画,使用IE内核的webbrowser不能播放,使用基于WebKit和Cefsh ...
- java 中类的方法
object类,即所有类的父类, getClass() 返回对象执行时的Class实例, getClass().getName();// 返回类的名字 toString();// equals();/ ...
- day 23-1 类的命名空间、组合
类的命名空间 类与对象命名空间 类里 可以定义两种属性 静态属性 动态属性 类中的静态变量 可以被对象和类调用对于不可变数据类型来说,类变量最好用类名操作对于可变数据类型来说,对象名的修改是共享的,重 ...
- arguments.callee.caller
1.Arguments Arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性l ...
- [精品书单]word排版设计
- DC综合简单总结(2)
DC综合简单总结(2) 建立时间和保持时间和数据输出延时时间 一.概念 建立时间和保持时间都是针对触发器的特性说的. 建立时间(Tsu:set up time) 是指在触发器的时钟信号上升沿到来以前, ...
- shell的进度条【转】
生成进度条的俩个shell脚本 !/bin/bash i= bar='' index= arr=( "|" "/" "-" "\\ ...