websocket详解

什么是websocket,与http有什么区别?

1、WebSocket 是一种网络通信协议,本质上是一个基于tcp的协议,是一个持久化的协议,客户端与服务端任意一方
都可以建立连接将数据推向另一方,只需要建立一次连接,就可以一直保持,协议名为"ws"2、http是一种无状态,无连接,单向的应用层协议,通信请求只能由客户端发起,服务端对请求做出应答处理。
都是通过javascript与ajax进行轮询,效率低,非常的浪费资源。
3、WebSocket在建立握手时,数据是通过HTTP传输的。但是建立之后,在真正传输时候是不需要HTTP协议的。

实际开发

WebSocketConfig配置

package com.elink.base.websocket;


import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * WebSocketConfig配置
 */
@Configuration
public class WebSocketConfig {

    @Bean
    @ConditionalOnBean(TomcatEmbeddedServletContainerFactory.class)
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

}

WebSocketServer服务类

注意在使用服务类时,需要配置nginx代理
location ^~ /xueHuiShenBao/websocket/ {
	proxy_pass http://127.0.0.1:9996/xueHuiShenBao/websocket/;   
	 proxy_http_version 1.1;
	 proxy_set_header Upgrade $http_upgrade;
	 proxy_set_header Connection "upgrade";
	 proxy_read_timeout 1800s;
}
package com.elink.base.websocket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

@Component
@ServerEndpoint("/websocket/{userId}")
public class WebSocketServer {

    private static final Logger logger = Logger.getLogger(String.valueOf(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) {
        this.session = session;
        this.userId = userId;

        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            webSocketMap.put(userId, this);
            //加入set中
        } else {
            webSocketMap.put(userId, this);
            //加入set中
            addOnlineCount();
            //在线数加1
        }
        logger.info("用户连接:" + userId + ",当前在线人数为:" + getOnlineCount());
        try {
            sendMessage("连接成功");
        } catch (IOException e) {
            logger.info("用户:" + userId + ",网络异常!!!!!!");
        }


    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if (webSocketMap.containsKey(userId)) {
            webSocketMap.remove(userId);
            //从set中删除
            subOnlineCount();
        }
        logger.info("用户退出:" + userId + ",当前在线人数为:" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("用户消息:" + userId + ",报文:" + message);
        //可以群发消息
        //消息保存到数据库、redis
        if (StringUtils.isNotBlank(message)) {
            try {
                //解析发送的报文
                JSONObject jsonObject = JSON.parseObject(message);
                //追加发送人(防止串改)
                jsonObject.put("fromUserId", this.userId);
                String toUserId = jsonObject.getString("toUserId");
                String contentText = jsonObject.getString("contentText");


                //传送给对应toUserId用户的websocket
                if (StringUtils.isNotBlank(toUserId) && webSocketMap.containsKey(toUserId)) {
                    webSocketMap.get(toUserId).sendMessage(jsonObject.toJSONString());
                } else {
                    logger.info("请求的userId:" + toUserId + "不在该服务器上");
                    //否则不在这个服务器上,发送到mysql或者redis
                }


            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.info("用户错误:" + this.userId + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }


    /**
     * 发送自定义消息
     */
    public static void sendInfo(String message, @PathParam("userId") String userId) throws IOException {
        logger.info("发送消息到:" + userId + ",报文:" + message);
        if (StringUtils.isNotBlank(userId) && webSocketMap.containsKey(userId)) {
            webSocketMap.get(userId).sendMessage(message);
        } else {
            logger.info("用户" + userId + ",不在线!");
        }
    }

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

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

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

}

前端代码

function initQrCode() {
     var socket;
     var ii = '';
     //生成17位随机数
     var coreCode = Math.round(Math.random() * 99999999999999999);
     if (typeof (WebSocket) == "undefined") {
         if (window.console) {
             console.log("您的浏览器不支持WebSocket");
         }
     }else {
         if (window.console) {
             console.log("您的浏览器支持WebSocket");
         }
         //实现化WebSocket对象,指定要连接的服务器地址与端口  建立连接
         let socketUrl = basePaht + 'websocket/' + coreCode;
         socketUrl = socketUrl.replace("https", "ws").replace("http", "ws");
         if (socket != null) {
             socket.close();
             socket = null;
         }
         socket = new WebSocket(socketUrl);

         //打开事件
         socket.onopen = function () {
             if (window.console) {
                 console.log("websocket已打开");
             }

             ajaxSubmit(
                 ajaxPath+ '/xieHuiContro/initQrCode',
                 {"coreCode":coreCode},
                 'json',
                 function (data) {
                 if (data.status == 0) {
                     var img = new Image();
                     img.src = 'data:image/png;base64,'+data.base64Pic;
                     $('#pagr-right-text').append(img);
                 }else {
                     $('#pagr-right-text').text("系统异常,请联系管理员!");
                 }
             });
         };

         //获得消息事件
         socket.onmessage = function (resMsg) {
             if (window.console) {
                 console.log(resMsg.data);
             }

             var msg = getObjToString(resMsg.data);
             if ("连接成功" != msg) {
                 if (msg == 'noData') {
                     layer.close(ii);
                     layer.msg('无数据!', {icon: 7});
                 } else if (msg == 'error') {
                     layer.close(ii);
                     layer.msg('出错,请稍后再试!', {icon: 7});
                 } 
             }
         };
         //关闭事件
         socket.onclose = function () {
             if (window.console) {
                 console.log("websocket已关闭");
             }
         };
         //发生了错误事件
         socket.onerror = function () {
             if (window.console) {
                 console.log("websocket发生了错误");
             }
             layer.msg('服务器忙请稍后再试。', {icon: 7});
             return false;
         }
     }
 }

你可能感兴趣的:(网络,websocket,websocket,java,网络协议)