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协议建立链接也必须要有三次握手才能 ...
随机推荐
- c中遍历lua的表
//遍历lua表,index为表在栈中的位置 void traverse_table(lua_State* L, int index) { lua_pushnil(L); stack_dump(L); ...
- python对象的三要素
id() 函数返回对象的唯一标识符,标识符是一个整数. 返回值 :返回对象的内存地址. >>>a = 'runoob' >>> id(a) 4531887632 i ...
- idea使用EasyCode集成ruoyi框架自动生成代码
1.ruoyi框架源码获取 https://gitee.com/zhangmrit/ruoyi-cloud/tree/nacos/ 2.需要ruoyi调整部分代码 public class BaseC ...
- 学习lua-04,json.util merge方法对集合处理的实际应用,及tostring方法
local jsonutil = require("json.util") local merge = require("json.util").merge l ...
- Windows MFC HTTP GET请求 函数流程
Windows MFC HTTP GET请求 函数流程 1 CString m_strHttpUrl(_T("http://10.200.80.86:8090/course/upload&q ...
- .NET CORE 下收发邮件之 MAILKIT
背景 利用代码发送邮件在工作中还是比较常见的,相信大家都用过SmtpClient来处理发送邮件的操作,不过这个类以及被标记已过时,所以介绍一个微软推荐的库MailKit来处理. MailKit开源地址 ...
- 微信小程序开发常见问题
1.不同页面之间的传值方式 通过URL问号传值 当前页面 wx.navigateTo({ url: '/pages/aaa/aaa?/userName=norma' }) 2. 另一个页面通过opti ...
- 【python_PAT_乙类】1013_数素数 ,Python运行超时解决方案
题目: 令 Pi 表示第 i 个素数.现任给两个正整数 M≤N≤104,请输出 PM 到 PN 的所有素数. 输入格式: 输入在一行中给出 M 和 N,其间以空格分隔. 输出格 ...
- down_interruptible()获取信号量
信号量(Semaphore)是操作系统中最典型的用于同步和互斥的手段,信号量的值可以是0.1或者n.信号量与操作系统中的经典概念PV操作对应. P(S):①将信号量S的值减1,即S=S-1:②如果S≥ ...
- CentOS安装并查看lm_sensors CPU温度监控
CentOS安装并查看lm_sensors 首先查看是否安装rpm包: [root@localhost home]# rpm -qa|grep sensors lm_sensors-libs-3.1. ...