侧边栏壁纸
博主头像
小白博主等级

just do it!

  • 累计撰写 60 篇文章
  • 累计创建 77 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

WebScoket初识

小白
2019-09-08 / 0 评论 / 0 点赞 / 115 阅读 / 1,310 字

简介

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。其使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。

WebSocket事件

  • open事件(建立一个websocket连接时触发),事件处理程序即事件回调函数Socket.onopen
  • message事件(接收消息时触发),事件处理程序即事件回调函数Socket.onmessage
  • error事件(连接发生错误时触发),事件处理程序即事件回调函数Socket.onerror
  • close事件(连接关闭时触发),事件处理程序即事件回调函数Socket.onclose

WebSocket方法

  • Socket.send(message),使用连接发送数据方法
  • Socket.close(),关闭连接方法

数据传输

WebSocket之间的数据传输都是传输字符串,前端建立socket连接,连接到远程websocket服务上,之后每次数据交互都是通过与远程websocket连接交互进而与其他连接到远程webSocket服务的连接进行通信,因此可以自行设置前端与远程webSocket交互的数据格式,例如JSON数据格式,在发送数据时,前端将JSON格式转换成字符串进行发送,前端接受到数据时,接收到的一定是字符串数据,根据开发规约,自行解析数据。

前端实例(H5)

//建立一个websocket连接
let socket=new WebSocket("ws://127.0.0.1:7080/webSocket/"+this.state.userName);
//连接建立回调函数
socket.onopen=function () {
    message.info("socket连接已打开");
    that.state.userModelShow=false;
    that.forceUpdate();
};
//收到消息的处理函数
socket.onmessage=function (msg) {
    let data=msg.data;
    let arr=data.split("#antsitya#");
    let type=arr[0];
    let content=arr[1];
    let userName="";
    let time=new Date();
    let onlineCount=that.state.onlineCount;
    if(type==="SYS_NOTICE"){
        content=arr[1].split("#ONLINECOUNT#")[0];
        onlineCount=arr[1].split("#ONLINECOUNT#")[1];
    }
    if(type==="NEWS_OTHER"){
        content=arr[1];
        userName=arr[2];
    }
    let msgNew={
        type:type,
        userName:userName,
        content:content,
        time:time,
     };
     let news=that.state.Msg;
     news.push(msgNew);
     that.setState({
         Msg:news,
         onlineCount:onlineCount,
     })
};
//连接关闭的回调函数
socket.onclose=function () {
    message.info("聊天通道已关闭!")
};
//连接出错的回调函数
socket.onerror=function () {
    message.error("socket连接异常")
};

Java实现远程WebSocket服务(Spring Boot)

加入websockt依赖

//pom.xml文件
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

配置webSocket

//编写WebSocket配置,创建websocket bean实例
//自动注册使用了@ServerEndpoint注解声明的Websocket endpoint
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

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

编写接受webSocket处理连接操作类

//消息接收处理 websocket 连接、关闭、发送消息等钩子。
import com.ant.chat_room.Utils.StringUtils;
import lombok.extern.log4j.Log4j2;
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.Collections;
import java.util.HashMap;
import java.util.Map;

@Log4j2
@ServerEndpoint("/webSocket/{userId}")
@Component
public class WebSocketServer {
    private final String MSG_FIX="#antsitya#";
    private static int onlinCount=0;
    private static Map<String,WebSocketServer> users= Collections.synchronizedMap(new HashMap<>());
    private Session session;
    private String userName;

    public static synchronized int getOnlinCount(){
        return onlinCount;
    }

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

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

    public static synchronized boolean vaildUserName(String userName){
        return users.get(userName)==null;
    }

    /**
     * 客户端建立webSocket连接
     * @param session
     * @param userName
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userName){
        this.session=session;
        this.userName=userName;
        users.put(userName,this);
        addOnlineCount();
        log.info(userName+"加入群聊,当前在线人数为"+getOnlinCount());
        try{
//            this.session.getBasicRemote().sendText("连接成功");
            sendToAll("SYS_NOTICE","已加入群聊"+"#ONLINECOUNT#"+getOnlinCount(),userName);
        }catch (IOException e){
            e.printStackTrace();
            log.error("error happen on function onOpen"+e);
        }
    }

    /**
     * 客户端管理webSocket连接
     */
    @OnClose
    public void onClose(){
        users.remove(this.userName);
        subOnlineCount();
        try{
//            this.session.getBasicRemote().sendText("连接成功");
            sendToAll("SYS_NOTICE","已退出群聊"+"#ONLINECOUNT#"+getOnlinCount(),this.userName);
        }catch (IOException e){
            e.printStackTrace();
            log.error("error happen on function onOpen"+e);
        }
        log.info(this.userName+"已退出群聊,当前在线人数为:"+getOnlinCount());
    }

    /**
     * 收到客户端出发的消息后出发的方法
     */
    @OnMessage
    public void onMessage(String message){
        log.info("收到客户端发送的消息,内容为:"+message);
        try{
            //群聊发送消息
            if(StringUtils.isNotEmpty(message)){
                String[] arrMsg=message.split("@antsitya@");
                if(arrMsg.length==3){
                    sendToAll(arrMsg[0],arrMsg[1],arrMsg[2]);
                }else{
                    log.error("发送信息格式错误");
                }
            }
        }catch (IOException e){
            log.error("error happen on function onMessage ",e);
        }
    }

    /**
     *
     */
    @OnError
    public void onError(Session session,Throwable error){
        log.error("发生错误session:"+session);
        error.printStackTrace();
    }
    //给特定人员发送消息
    public void sendMessageToSomeBody(String userName,String message)throws IOException{
        if(users.get(userName)==null) return;
        users.get(userName).session.getBasicRemote().sendText(message);
        this.session.getBasicRemote().sendText(this.userName+"@"+userName+":"+message);
    }
    //群发消息
    public void sendToAll(String type,String message,String userName) throws IOException{
        for(WebSocketServer socketServer:users.values()){
            String Msg=type+MSG_FIX;
            try{
                if(type.equals("SYS_NOTICE")){
                    Msg=Msg+(socketServer.userName.equals(userName)?"您":userName)+message;
                    socketServer.session.getBasicRemote().sendText(Msg);
                }
                if(type.equals("NEWS_OTHER")){
                    Msg=Msg+message+MSG_FIX+userName;
                    if(!socketServer.userName.equals(userName)){
                        socketServer.session.getBasicRemote().sendText(Msg);
                    }
                }
            }catch (IOException e){
                continue;
            }
        }
    }
}
0

评论区