springboot的websocket因IP问题无法连接
首先遇到这个问题有点奇葩,出现在项目上线时的客户现场,头两天一直都无法确定原因,因为它的表现方式很奇怪,基于springboot实现的websocket,同样的代码在公司研发环境不会有问题,客户现场会出现浏览器一连接就马上断开,没有使用任何代理服务器,服务器没有任何异常,就是浏览器直接断开,最后排除现场环境和公司环境差异性,不断保持两边的一直性,最有可能的一项,能想到的人不多了,IP地址不一样,我一开始是不相信的,IP地址不一样会导致这种问题?
我注重测试验证理论,试一把再说,结果就可以了,同样的服务器在192.168.x.x这种网段下不会有问题,如果是34.69.x.x这种短IP就不行,本人对网络不是很了解,同样的服务器和一模一样的代码,仅仅一个IP不同就会造成websocket无法使用吗?我知道的方法和网上的参考资料全部试了一下,无法解决,如果有知道的朋友可以留言。
此路不同就换一条路,我决定放弃springboot的websocket实现,尝试tomcat服务器的websocket实现,解决了此问题。
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
java代码
import com.bootdo.common.utils.JSONUtils;
import com.bootdo.system.domain.UserDO;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; @ServerEndpoint(value = "/endpointChat", configurator=GetHttpSessionConfigurator.class)
@Component
public class WebSocketSession {
private static final Logger logger = LoggerFactory.getLogger(WebSocketSession.class);
private static Map<String, WebSocketSession> clients = new ConcurrentHashMap<String, WebSocketSession>();
private Session session;
private String userSessionId;
private static String mark = "_";
private static String destinationPrefix = "/user";
private List<String> theme = new ArrayList<>();
@OnOpen
public void onOpen(Session session,EndpointConfig config) {
HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName()); SimplePrincipalCollection principalCollection = (SimplePrincipalCollection) httpSession
.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
UserDO userDO = (UserDO) principalCollection.getPrimaryPrincipal(); session.setMaxTextMessageBufferSize(1024 * 100 * 5);
session.setMaxBinaryMessageBufferSize(1024 * 100 * 5);
this.userSessionId = userDO.getUserId().toString()+mark+session.getId();
this.session = session;
clients.put(this.userSessionId, this);
} @OnClose
public void onClose(Session session) {
try {
clients.remove(userSessionId);
}catch (Exception e){
logger.error(e.getMessage(),e);
}
} @OnError
public void onError(Session session, Throwable error) {
clients.remove(userSessionId);
try {
session.close();
} catch (IOException e) {
logger.error("close session failed {}", e.getMessage());
}
} /**
* 收到客户端消息后调用的方法
* @param message
*/
@OnMessage
public void onMessage(String message, Session session) {
SimpleTextMsg msgObj = JSONUtils.jsonToBean(message, SimpleTextMsg.class);
if(msgObj.getOption().equals(WebSocketClientOption.REGISTER_THEME)){//client在连接成功之后,注册监听主题
theme.add(msgObj.getTheme());
}
} public static void convertAndSendToUser(String userId, String theme, String jsonData) {
synchronized (userId.intern()){
try{
for (WebSocketSession item : clients.values()) {
String idKey = userId+mark+item.getUserSessionId().split(mark)[1];
if (item.getUserSessionId().equals(idKey)){
if(item.getTheme().contains(destinationPrefix+theme)){//判断该session的用户是否订阅主题
SimpleTextMsg textMsg = new SimpleTextMsg();
textMsg.setBody(jsonData);
textMsg.setTheme("/user"+theme);
item.session.getBasicRemote().sendText(JSONUtils.beanToJson(textMsg));
}
}
}
}catch (Exception e){
logger.error(e.getMessage(),e);
}
}
} public String getUserSessionId() {
return userSessionId;
} public void setUserSessionId(String userSessionId) {
this.userSessionId = userSessionId;
} public List<String> getTheme() {
return theme;
} public void setTheme(List<String> theme) {
this.theme = theme;
} public static Map<String, WebSocketSession> getClients() {
return clients;
}
}
html5_websocket.js 核心方法
//开始之前请引入reconnecting-websocket.js
var ipRe=/^(\d+)\.(\d+)\.(\d+)\.(\d+).*$/;//正则表达式
function SxpSockJS(url){
this.host = window.location.host; if(ipRe.test(url)){
this.url = url;
}else if(url.indexOf("http") == 0 || url.indexOf("https") == 0){
this.url = url.splice("//")[1];
}else{
this.url = this.host + url;
}
console.log("connection url:"+this.url);
this.websocket = null;
this.subscribe = function(theme, callBack){//theme订阅主题,callBack回调函数
this.websocket.themeMap[theme] = callBack;
this.websocket.send("{theme:'"+theme+"',option:'registerTheme'}");
};
this.connect = function(onOpen,onError){
this.websocket = new ReconnectingWebSocket("ws://"+this.url,null,{reconnectInterval: 3000});
this.websocket.themeMap = {};
this.websocket.timeoutInterval = 5400;
this.websocket.onopen = function(event){
console.log("漂亮!与服务器websocket连接成功!!!");
if(onOpen && typeof onOpen === "function")onOpen();
};
this.websocket.onclose = function(event){
console.log("悲剧!与服务器websocket连接断开!!!");
if(onError && typeof onOpen === "function")onError();
};
this.websocket.onmessage = function (data) {
console.log(data.timeStamp+"<<< CONNECTED");
var obj = eval('(' + data.data + ')');
var callBack = this.themeMap[obj.theme];
if(callBack){
console.log("theme:"+obj.theme);
console.log("jsonData:"+obj.body);
callBack(obj);
}
console.log(data.timeStamp+"<<< END");
console.log(" ");
}
}
}
js调用代码
function init() {
var sock = new SxpSockJS(ctx+"endpointChat");
sock.connect(function() {//异步
sock.subscribe("/user/queue/prisoncellOnLine", handleNotification);
sock.subscribe("/user/queue/prisoncellAreaWarn", personAreaWarn);
sock.subscribe("/user/queue/prisoncellOffLine", personOffLine);
sock.subscribe("/user/queue/personSignEnd", personSignEnd);
sock.subscribe("/user/queue/personSignStart", personSignStart);
sock.subscribe("/user/queue/prisoncellFlush",prisoncellFlush);
},function(){
//异常处理逻辑
});
}
这里用到了一个websocket重连的函数,需要下载一个js,reconnecting-websocket.min.js
springboot的websocket因IP问题无法连接的更多相关文章
- 基于springboot的websocket聊天室
WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...
- SpringBoot+Vue+WebSocket 实现在线聊天
一.前言 本文将基于 SpringBoot + Vue + WebSocket 实现一个简单的在线聊天功能 页面如下: 在线体验地址:http://www.zhengqingya.com:8101 二 ...
- WebSocket的简单认识&SpringBoot整合websocket
1. 什么是WebSocket?菜鸟对websocket的解释如下 WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务 ...
- Springboot整合Websocket遇到的坑
Springboot整合Websocket遇到的坑 一.使用Springboot内嵌的tomcat启动websocket 1.添加ServerEndpointExporter配置bean @Confi ...
- SpringBoot 整合 WebSocket
SpringBoot 整合 WebSocket(topic广播) 1.什么是WebSocket WebSocket为游览器和服务器提供了双工异步通信的功能,即游览器可以向服务器发送消息,服务器也可以向 ...
- SpringBoot集成WebSocket【基于纯H5】进行点对点[一对一]和广播[一对多]实时推送
代码全部复制,仅供自己学习用 1.环境搭建 因为在上一篇基于STOMP协议实现的WebSocket里已经有大概介绍过Web的基本情况了,所以在这篇就不多说了,我们直接进入正题吧,在SpringBoot ...
- SpringBoot基于websocket的网页聊天
一.入门简介正常聊天程序需要使用消息组件ActiveMQ或者Kafka等,这里是一个Websocket入门程序. 有人有疑问这个技术有什么作用,为什么要有它?其实我们虽然有http协议,但是它有一个缺 ...
- springboot整合websocket原生版
目录 HTTP缺点 HTTP websocket区别 websocket原理 使用场景 springboot整合websocket 环境准备 客户端连接 加入战队 微信公众号 主题 HTTP请求用于我 ...
- 使用springboot+layim+websocket实现webim
使用springboot+layim+websocket实现webim 小白技术社 项目介绍 采用springboot和layim构建webim,使用websocket作为通讯协议,目前已经能够正 ...
- springboot集成websocket的两种实现方式
WebSocket跟常规的http协议的区别和优缺点这里大概描述一下 一.websocket与http http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能 ...
随机推荐
- 关于el-dialog弹窗组件关闭报错事件
以下写法,向父组件抛出关闭事件, (正常点击弹窗footer的关闭时没有报错,但是点击空白处及右上角的×号,就会报以上错误) 原因, close事件为已经关闭了弹窗后的事件,官方还给出了 befor ...
- NIO 缓冲区 ByteBuffer 基本认识
一.差别 java.nio.HeapByteBuffer 0. 获取方式:ByteBuffer.allocate(int value); 1. java堆内存,读写效率较低,但分配内存较块. 2. 受 ...
- lui - pager - 分页
pager - 分页 demo lui demo <template> <div class="app-container"> <h3>el-p ...
- 【STM32】NVIC嵌套中断向量控制器与外部中断
两种优先级 抢占优先级PreemptPriority:中断服务函数正在执行时,抢占优先级高的可以打断抢占优先级低的,实现中断的嵌套,相当于51的"高优先级" 响应优先级(子优先级) ...
- Docker学习——Dockerfile 指令详解(五)
我们已经介绍了 FROM (指定基础镜像) , RUN(执行命令) ,还提及了 COPY , ADD ,其实 Dockerfile 功能很强大,它提供了十多个指令.下面我们继续讲解其他的指令. COP ...
- 配置SASS过程
1.首先在电脑上安装Node.js 2.其次在命令行配置npm,命令:npm init.运行后会创建一个package.json文件 3.然后输入命令配置npm中可以使用SASS的包,命令:npm i ...
- win10查看笔记本电池性能
要生成电池报告,可以按Windows + R,窗口中输入 cmd 回车. 在提示符处输入: Powercfg /batteryreport,回车. 就可以在C盘看到性能报告文件.
- Python openpyxl【包】
介绍 Excel是我们日常工作中经常用到的办公软件,在处理数据和表格方面有着优异的性能,那么能不能用python来操作Excel呢? 答案是肯定的,openpyxl是一个第三方库,可以处理xlsx格式 ...
- jquery 判断字符串长度
function titleLength(str) { var strLength = 0; var list = str.split(""); for (var i = 0; i ...
- PHP Redis - 事务
Redis 事务可以一次执行多个命令, 并有两个重要的保证: ① 事务是一个单独的隔离操作:事务中的所有命令都会序列化.按顺序地执行.事务在执行的过程中,不会被其他客户端发送来的命令请求所打断. ② ...