/**
* 服务端
*/
@ServerEndpoint(value = "/websocket",configurator=GetHttpSessionConfigurator.class)
public class WebSocketUtil {
//用来存放每个客户端对应的WebSocketTest对象,适用于同时与多个客户端通信
public static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();
//若要实现服务端与指定客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
public static ConcurrentHashMap<Session,Object> webSocketMap = new ConcurrentHashMap<Session,Object>();
//与某个客户端的连接会话,通过它实现定向推送(只推送给某个用户)
private Session session;
/**
* 连接建立成功调用的方法
*
* @param session
* 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
webSocketSet.add(this); //加入set中
webSocketMap.put(session,this); //加入map中
System.out.println("一个连接开启");
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(Session session) {
webSocketSet.remove(this); //从set中删除
webSocketMap.remove(closeSession); //从map中删除
System.out.println("一个连接关闭");
}
/**
* 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
*
* @param message
* @throws IOException
*/
public static void sendMessage(String message) {
//给客户端发送消息
synchronized(session) {
try {
session.getBasicRemote().sendText(json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
var websocket;
var connectLock = false;
var wsUrl;
//开启连接
function connect(){
//判断当前浏览器是否支持WebSocket
if ('WebSocket' in window) {
var hostname = location.hostname;
var port = location.port;
wsUrl = "ws://" + hostname + ":" + port + webRoot + "/websocket";
websocket = new WebSocket(wsUrl);
} else {
alert('当前浏览器 Not support websocket')
}
}
function openWebSocket() {
connect();
//接收到消息的回调方法
websocket.onmessage = function(event) {
var data = event.data;
var result;
console.log(data);
heartCheck.reset().start();
if(data != 'ok'){
result = JSON.parse(event.data);
}
//如果不为空,则显示图片
if (result && result.id && result.id.length > 0) {
var time = result.remainTimes;
console.log(time)
if (time <= 0) {
sendDefaultResult(result.id, 4);
return;
}
if (!hasImage) {
showImage(result);
}
}
}
websocket.onopen = function(){
heartCheck.reset().start(); //心跳检测重置
console.log("llws连接成功!"+new Date().toUTCString());
};
websocket.onclose = function(){
console.log("llws连接关闭!"+new Date().toUTCString());
reconnect(wsUrl);
}
websocket.onerror = function(){
console.log("llws连接错误!");
reconnect(wsUrl);
}
}
function reconnect(url){
if(connectLock) return;
connectLock = true;
setTimeout(function(){ //没连接上会一直重连,设置延迟避免请求过多
connect();
connectLock = false;
},2000);
}
//心跳检测
var heartCheck = {
timeout: 10000,
timeoutobj:null,
serverTimeoutObj:null,
reset:function(){
clearTimeout(this.timeoutObj);
clearTimeout(this.TimeoutObj);
return this;
},
start:function(){
var self=this;
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳信息
//onmessage拿到返回的心跳就说明连接正常
websocket.send("HeartBeat");
console.log("HeartBeat!");
self.serverTimeoutObj=setTimeout(function(){
//如果超过一定时间还没重置,说明后端主动断开了
//如果onclose会执行reconnect,我们执行ws.close()就行了,如果直接执行reconnect会触发onclose导致重连两次
//websocket.close();
},self.timeout)
},this.timeout);
}
}
//监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
connectLock = false;
if(websocket){
websocket.close();
}
}