使用Websocket通信协议实现实时消息推送

博主最近做的项目有这样一个需求,需要将某监控系统的监控数据实时推送到web页面,以及集群之间的数据推送,这就可以使用Websocket来实现。

1.什么是Websocket?(以下说明copy来的)

WebSocket 协议在2008年诞生,2011年成为国际标准。现在所有浏览器都已经支持了。WebSocket 的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,实现真正的双向平等对话。

2.Websocket能做什么?

1.网页在线聊天

2.多人在线游戏

3.在线股票网站

4.在线新闻网站

5.应用集群之间的通信

6.远程系统/软件的状态和性能的实时监控

以上只是一部分,Websocket能做的远不止这些。

3.主要介绍Java WebSocket和javascript中的websocket的使用,js中websocket就是扮演一个客户端的角色,Java中的WebSocket分两种角色,一种是Java客户端终端的WebSocket(作用类似于JavaScript中的WebSocket),还有一种角色是Java服务器终端。

4.Websocket客户端

创建一个Websocket对象:

var webSocket = new WebSocket("ws://localhost:8001/socket");

在websocket中有几个常见方法:

  webSocket.onopen=function (event) {
        //连接成功时触发    
    }
    webSocket.onclose=function (event) {
        //连接关闭时触发    
    }
    webSocket.onerror=function (event) {
        event.data拿到错误信息
        //连接出错时触发    
    }
    webSocket.onmessage=function (event) {
        event.data拿到消息
        //收到消息时触发    
    }


    //向服务端发送消息
    webSocket.send(msg)

    //关闭当前Websocket连接
    webSocket.close()

websocket还定义了一个readyState属性,这个属性可以返回websocket所处的状态:
1、CONNECTING(0) websocket正尝试与服务器建立连接
2、OPEN(1) websocket与服务器已经建立连接
3、CLOSING(2) websocket正在关闭与服务器的连接
4、CLOSED(3) websocket已经关闭了与服务器的连接

if(webSocket.readyState==WebSocket.OPEN){/*do something*/}

5.Web页面测试代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<input type="button" value="连接" id="btnClick1"><br>
<input type="text" id="msg"><input type="button" value="发送" id="btnClick2">
</div>
<div id="resultDiv"></div>
<script src="js/jquery-1.12.4.js" type="text/javascript"></script>
<script>
    var webSocket;

    $("#btnClick2").click(function () {
        var msg = $("#msg").val();
        $("#resultDiv").append("<p>发送消息:" + msg+"</p>");
        webSocket.send(msg)
    });
    $("#btnClick1").click(function () {
        $("#resultDiv").append("<p>开始连接服务端!</p>");
        webSocket = new WebSocket("ws://localhost:8001/socket");
        webSocket.onerror = function (event) {
            $("#resultDiv").append("<p>onerror:" + event.data + "</p>");
        }
        webSocket.onopen = function (event) {
            $("#resultDiv").append("<p>连接成功!</p>");
        }
        webSocket.onmessage = function (event) {
            $("#resultDiv").append("<p>onmessage:" + event.data + "</p>");
        }
    });

</script>
</body>
</html>

6.服务端配置

@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

7.服务端逻辑代码

注意记得加上@Component,不加会出现握手失败404错误,注解@ServerEndpoint后跟的地址就是请求地址,且可以跟参数,如@ServerEndpoint(value = "/socket/{id}"),@ServerEndpoint(value = "/socket/{name}"),跟参数后,可在方法参数中使用注解@PathParam(value = "name")来获取。如跟用户绑定的参数,记得在服务端设置对应属性,如private String name,且在连接成功时赋值;

@ServerEndpoint(value = "/socket")
@Component
public class WebSocketServer {
    //用来记录当前在线连接数,线程安全。
    private static int onlineCount = 0;

    //线程安全Set,存放每个客户端的MyWebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();

    //与某个客户端的连接会话
    private Session session;

    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session) {
        System.out.println(session.getAsyncRemote());
        this.session = session;
        webSocketSet.add(this);     //加入set中
        addOnlineCount();           //在线数加1
        sendMessage("有新连接加入!当前在线人数为" + getOnlineCount());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);  //从set中删除
        subOnlineCount();           //在线数减1
        sendMessage("有用户退出!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(String message, Session session){
        System.out.println("来自客户端的消息:" + message);
        //群发消息
        sendInfo("服务端返回:"+session.getId()+"-"+message);
    }

    /**
     * 发生错误时调用
     * @OnError
     **/
    @OnError
    public void onError(Session session, Throwable error) {
        System.out.println("发生错误");
        error.printStackTrace();
    }

    /**
     * 向客户端发送消息
     * @param message 消息内容
     * */
    private void sendMessage(String message) {
        this.session.getAsyncRemote().sendText(message);
    }


    /**
     * 群发自定义消息
     * */
    private static void sendInfo(String message){
        for (WebSocketServer item : webSocketSet) {
            item.sendMessage(message);
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }
}

8.测试结果如图:

猜你喜欢

转载自blog.csdn.net/weixin_46792649/article/details/105932845