WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
主要是js完成,直接上代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>websocket</title>
<style>
.sss {
width: 15px;
height: 15px;
color: #fff;
float: right;
margin-right: -5px;
margin-top: -3px;
background-color: #f00;
border-radius: 50%;
}
</style>
</head>
<script>
var username = window.parent.document.getElementById('i_name').innerText
var socket;
function openSocket() {
if(typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
}else{
console.log("您的浏览器支持WebSocket");
//实现化WebSocket对象,指定要连接的服务器地址与端口 建立连接
var socketUrl="http://192.168.0.107:8888/imserver/"+username;
socketUrl=socketUrl.replace("https","ws").replace("http","ws");
console.log(socketUrl);
if(socket!=null){
socket.close();
socket=null;
}
socket = new WebSocket(socketUrl);
//打开事件
socket.onopen = function() {
console.log("websocket已打开");
};
//获得消息事件
socket.onmessage = function(msg) {
console.log(msg.data);
updateState(msg.data);
};
//关闭事件
socket.onclose = function() {
console.log("websocket已关闭");
};
//发生了错误事件
socket.onerror = function() {
console.log("websocket发生了错误");
}
}
}
// 发送消息
function sendMessage() {
if(typeof(WebSocket) == "undefined") {
console.log("您的浏览器不支持WebSocket");
}else {
console.log("您的浏览器支持WebSocket");
socket.send('你好WebSocket...');
}
}
// 将消息显示在网页上
function updateState(str) {
if(str== "1"){
document.getElementById("red_dot").style.visibility="visible";//显示
}else{
document.getElementById("red_dot").style.visibility="hidden";//隐藏
}
}
if(username != null && username != "" && username.length > 0){
openSocket();
}
</script>
<body style="text-align:center;">
<div id="red_dot" class="sss" style="visibility: hidden;"></div>
</body>
</html>
首先检查浏览器是否支持。目前大部分浏览器都已支持。
第一步,拿到父页用户登录名称 作为与服务端连接的用户id。
第二步,连接服务端和一系列的监听事件。
第三步,通过不同的事件以及不同的数据对页面相应的操作。
解释:我的需求比较简单,主要是后台提醒作用,后台推送1,前台显示红点提醒,推送为其他则隐藏红点。
如果语法错误需要安装express和socket.io库
父页面代码:
<i id="i_name" hidden="hidden">{{user.username}}i>
<iframe id="topFrame" src="im_client.html" width="18px" height="32px" scrolling="No" noresize="noresize" frameborder="0">iframe>
项目环境是 springboot + Maven + WebSocket。话不多说,看代码
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-websocketartifactId>
dependency>
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* 开启WebSocket支持
*/
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.stereotype.Component;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
@ServerEndpoint("/imserver/{userId}")
@Component
public class WebSocketServer {
static Log log=LogFactory.get(WebSocketServer.class);
/**静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。*/
private static int onlineCount = 0;
/**concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。*/
private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
/**与某个客户端的连接会话,需要通过它来给客户端发送数据*/
private Session session;
/**接收userId*/
private String userId="";
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session,@PathParam("userId") String userId) {
System.out.println("userId:"+userId + " , session:"+session);
this.session = session;
this.userId=userId;
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
webSocketMap.put(userId,this);
//加入set中
}else{
//加入set中
webSocketMap.put(userId,this);
//在线数加1
addOnlineCount();
}
log.info("用户连接:"+userId+",当前在线人数为:" + getOnlineCount());
// try {
// sendMessage("连接成功");
// } catch (IOException e) {
// log.error("用户:"+userId+",网络异常!!!!!!");
// }
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
if(webSocketMap.containsKey(userId)){
webSocketMap.remove(userId);
//从set中删除
subOnlineCount();
}
log.info("用户退出:"+userId+",当前在线人数为:" + getOnlineCount());
}
/**
* 接收客户端消息
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("用户消息:"+userId+",报文:"+message);
}
/**
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("用户错误:"+this.userId+",原因:"+error.getMessage());
error.printStackTrace();
}
/**
* 发送自定义消息 群发
* */
public static void sendAllInfo(String message) {
try{
Collection<WebSocketServer> mCollection = webSocketMap.values();
for (WebSocketServer mWebSocketServer:mCollection) {
mWebSocketServer.sendMessage(message);
}
}catch (Exception e){
e.getMessage();
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
静态方法 类名点直接调用即可
WebSocketServer.sendAllInfo("0");
亲测可用