WebSocket协议理解并实现在线聊天

这篇具有很好参考价值的文章主要介绍了WebSocket协议理解并实现在线聊天。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

写在前面

WebSocket 简称 ws
本文通过介绍ws,然后一步步的使用ws协议进行前后端开发测试,最后使用SpringBootvue 利用ws协议达实现一个在线聊天室的小demo(源码在文章末尾)。

看完此篇后将能够完成这样的小demo(需要会使用springboot和vue2以及element-ui)
websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue

WebSocket介绍

websocket在线连接,小项目,笔记,websocket,spring boot,vue
WebSocket是在HTML5开始提供的一种能在单个TCP连接上进行全双工通讯的网络通信协议
与HTTP协议可以简单理解为:
websocket在线连接,小项目,笔记,websocket,spring boot,vue
WebSocket协议与HTTP协议对比:

  • HTTP协议:HTTP协议是一种无状态(请求完成后,连接彻底断开,节省资源)无连接(客户端端向服务端请求数据,获取数据后即断开连接)单向(连接建立只能由客户端发起)的应用层通信协议,采用请求/响应模型。
    • 特性:客户端有事向服务器询问,服务器告诉它,告诉完毕后客户端没有问题就消失的无影无踪,服务器再也找不到它,只能等到客户端下次有问题去询问服务器它才会出现。服务器在明处,客户端在暗处。
    • 弊端,客户端有事向服务端询问可以,但服务端有事却找不到客户端,因为客户端完成数据获取后,连接被彻底断开,而掌握建立连接的特权只在客户端手中,只能把事憋到客户端与服务端再次建立请求时一并告诉它。当有要紧事的时候,也无法联系客户端,即服务端无法向客户端推送数据
    • 解决思路:让客户端频繁的去与服务端建立连接,这样服务端的数据就不用憋太久
      • 存在的问题:多久去与客户端建立一次连接呢?首先频繁的建立耗费系统大量的资源,而服务端却很少有数据传输;其次,多久建立一次连接呢?连接建立的过于频繁,客户端会承受不住,如果频率低,服务器的数据还是要憋一会,还是打达不到实时。频繁访问耗费巨大资源洒下大网只有极少收获。

要是有一种客户端能向服务器端发送数据,服务器端也能向客户端发送数据的协议就好了!即全双工通讯 。这种协议客户端不能与服务端断开连接,使得服务端端能够找到客户端继续发送数据即有状态连接虽然会耗费资源,但在特定需求下,比HTTP协议那种频繁连接要好上不少。这种协议就是WebSocket协议。总结webSocket就是支持持久连接使得服务端与客户端都能够实时通信的协议

WebSocket的应用场景

  • 及时通信的Web应用:例如要求网页数据实时刷新的实时数据展示网站
  • 游戏应用:屏幕动画能够实时刷新
  • 聊天应用:发送消息能够及时接收,推送

websocket在线连接,小项目,笔记,websocket,spring boot,vue
推荐文章

WebSocket实现

HTTP方式:我们编写前后端分离的代码时,后端编写@RestController接口,用来接收请求,前端编写封装axios用来发送请求获取后端数据。其实这种方式就是遵守HTTP协议进行数据交互的,前端使用axios发送的是HTTP请求,后端接口接收的也是HTTP请求。
WS方式
因为常使用的@RestController接口和axios请求工具都是为HTTP协议服务的,因此WS虽然数据交互是这一流程(后端指定接口,前端获取数据),但要有自己的一套实现工具。使用@ServerEndpoint到达类似于@RestController的效果,使用WebSocket对象达到类似于axios的效果,具体使用后面会介绍。 Endpoint与webScoket的关系就像 Servlet与Http的关系一样


生命周期
生命周期使我理解的,原话为 websocket事件
前端

let ws=new webSocket(ws://ip:端口号/资源名称)
函数名 描述
ws.onopen 建立连接时触发
ws.onmessage 接收到后端消息时触发
ws.onerror 通信过程发生错误时触发
ws.onclose 连接关闭时触发

发送数据时 ws.send()

后端

注解名 描述
@onClose 连接关闭时触发
@onOpen 初始化时触发
@onError 出现错误时触发
@onMessage 初始化后自动触发,获取前端传递的数据

ws实现流程概括
服务端不再像过去一样只负责客户端的数据响应,还可以主动向客户端推送数据
websocket在线连接,小项目,笔记,websocket,spring boot,vue
ws前后端都有一个生命周期的概念,后端的各个生命周期相当于把一个@RestController进行拆分同时多了一个连接者的容器。

  1. 进行请求映射使用@ServerEndpoint("xx")
  2. 请求初始化时将此请求放入所有连接者的容器,方便在发送请求时,能够找到当前与系统建立连接的各个连接,使用@OnOpen标记
  3. 获取前端的数据 @OnMessage,可以使用同@RequestMapping()的注解方式获取数据,如@PathParam("xxxx")注意每次前端发送数据,此方法都会被调用。但初始化时不会调用
  4. 返回给前端数据 不在直接使用return,而是使用获取连接池中保存的连接session,通过session将返回的信息进行传递。
  5. 消息的接收、返回都已经完成,其余的就是补充。关闭连接是调用 @OnClose标注下的方法,出现错误时调用@OnError标注下的方法

webSocket有自己获取参数的获取方式,与HTTP的Controller的方式很像

  • 从请求路径参数中获取数据 @PathParam("xxx") 使用起来与@PathValue("xxx")一样

有的注解下的方法必须含有某些参数

  • @OnError标识下的方法列表中必须含有Throwable对象,否则启动报错
  • @OnMessage此注解标识下的方法,在前端向后端发送消息时自动调用,要求此方法必须含有参数,否则启动报错

问题?

  • 在后端向前端发送信息时,怎样去调用?
    整个生命周期在连接时能够自动调用的有两个方法,一个是在初始化时调用@OnOpen标注下的方法,一次是在接受前端请求时 调用@OnMessage下的方法(此方法前端每次发送数据都会被调用)。可以选用@OnMessage标注下的方法作为后端向前端返回数据的引子,在此方法中调用返回前端的数据方法。

  • 怎样发到即时通讯效果?

  • 解决后端怎样向前端发送数据问题,即可以解决此问题。当A通过ws将发给B的消息传递到服务器,在接收前端数据的方法中自动调用返回前端数据的方法,在此方法中获取消息内容和目的方,然后去连接者容器中找到目的方的连接对象,然后将A发送的数据作为返回给B连接对象返回的数据。**这样思路就要求 B要在连接者的容器中,即B要保持连接 **

  • 怎样使得前台一直接收后端自己产生的数据
    后端自己产生的数据就代表前台只能触发一次,其余的数据不断返回前端都要靠着这一次触发。可以在第一次触发时调用一个类似于监听阻塞阻塞队列的方法,将产生的数据不断的放入队列中,方法中监听到数据就取出返回给前端。这样就是由第一次请求调用监听器,数据产生监听的去触发数据返回

  • 前端怎样接收后端返回的数据?
    当后端有数据返回时前端的对象的onmessage()会被触发,在这里可以就行数据的赋值,页面的渲染

ws参数传递

  • 路径传参:在初始化时通过路径进行参数传递 后端使用要在路径的映射中使用 例如: login/{xxx},然后在方法参数中使用@PathParam("xxx")去接收

  • 消息传参:使用对象发送消息ws.send(“xxx”),可以将一些内容转为JSON形式进行发送,然后后端在@OnMessage下的方法参数中进行接收和转换

  • 请求头传参:使用请求头,因为以上都已经介绍过,这里不加赘述。请求头才是这里重点

    • 前端添加请求头
      ws的请求不像HTTP请求那样灵活,没有api进行传参,且不可以自定义请求头。那怎样进行传递呢?
      • 利用websocket请求头有含Sec-WebSocket-Protocol这个属性,可以在为属性中赋值,后端从这个属性中取出。这个属性赋值没有单独的Api,只能在构造ws对象能够进行赋值
      例如 :
      let ws = new WebSocket("ws://localhost:8888/xxxx", "请求参数1");
      
      后端获取请求头 Sec-WebSocket-Protocol  得到的就是 请求参数1
      
      let ws = new WebSocket("ws://localhost:8888/xxxx", ["请求参数1","请求参数2"]);
      
      后端获取请求头 Sec-WebSocket-Protocol  得到的就是 请求参数1   请求参数2
      
    • 后端获取请求头
      后端这里指的就是springBoot,后端获取请求头没有HTTP协议那样直接在参数列表中使用注解 @RequestHeader直接获取,而是要继承的指定方法中获取

    websocket在线连接,小项目,笔记,websocket,spring boot,vue
    *

    @Configuration
    @Slf4j
    public class WebSocketConfig extends ServerEndpointConfig.Configurator {
        @Bean
        public ServerEndpointExporter serverEndpointExporter() {
            return new ServerEndpointExporter();
        }
    
        public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
    
            //获取请求头 请求头的名字是固定的
            List<String> list = request.getHeaders().get("Sec-WebSocket-Protocol");
    
    
            //当Sec-WebSocket-Protocol请求头不为空时,需要返回给前端相同的响应
            response.getHeaders().put("Sec-WebSocket-Protocol",list);
    
    
            super.modifyHandshake(sec, request, response);
        }
    }
    
    
    • 然后 还要在@ServerEndpoint注释中指名配置类
      websocket在线连接,小项目,笔记,websocket,spring boot,vue

    注意:此类的中方法只会在创建连接时执行,在发送消息、出现错误、断开连接均不执行
    个人理解:既然ws是创建一次就可以多次发送消息,在创建第一次时进行身份校验,同一个连接是不是只校验一次就可以了?http使用拦截器也是校验一次,因为其频繁连接才会频繁的验证?即在这个方法中充当http时的拦截器使用?
    websocket在线连接,小项目,笔记,websocket,spring boot,vue

模拟测试

后端模拟

后端使用springBoot,前端使用postman发送ws请求

后端准备: 注意要tomcat7以后才支持webSocket协议

  • 后端除去环境依赖外,要导入关键的WebSocket依赖

      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-websocket</artifactId>
      </dependency>
    
  • 环境依赖

     <parent>
       <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
        <relativePath/> 
     </parent>
    
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
     </dependency>
    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-websocket</artifactId>
     </dependency>
     <dependency>
         <groupId>org.projectlombok</groupId>
         <artifactId>lombok</artifactId>
         <optional>true</optional>
     </dependency>
    
  • 向容器中注入 ServerEndpointExporter对象
    创建一个配置类,在类中将对象注入容器

    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();
        }
    }
    
    
  • 接下来就可以写类似于接口的应用了

前端准备

  • 在postMan中创建ws类型的连接 (不能使用原HTTP的方式
    websocket在线连接,小项目,笔记,websocket,spring boot,vue

第一个测试:建立连接后,前端向后端发送数据,后端接收数据,并向前端发送数据;只有一个连接 (不使用连接的session们容器)


import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;

@ServerEndpoint(value = "/wsserver/{username}")
@Component
@Slf4j
public class WebSocketServer {
    private Session session;
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session){
        this.session=session;
        log.info(username);
        log.info("连接创建初始化");
    }

    @OnMessage
    public void onMessage(Session session,String message) throws IOException, InterruptedException {
        log.info("接收到数据"+message);
        Thread.sleep(10000);

        for (int i=0;i<10;i++){
            this.session.getBasicRemote().sendText("来自后端的数据");
        }
    }
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
    @OnClose
    public void onClose(){
        log.info("关闭连接");
    }
}


注释

websocket在线连接,小项目,笔记,websocket,spring boot,vue

测试结果
websocket在线连接,小项目,笔记,websocket,spring boot,vue
第二个测试:创建两个独立连接分别为A、B。A向B发送数据,B向A发送数据,在数据中要指定发送方

实现思路:

  • 数据中指明发送方接收方以及数据。在路径参数中指明发送方,在数据格式中设定规则,提取出接收方和数据。
  • 每一个连接在初始化时都会向公共的缓存中添加自己的标识session对象,这样就方便根据数据的接收方去找到其连接的session,然后将数据通过接收方的session进行返回
@ServerEndpoint(value = "/wsserver/{username}")
@Component
@Slf4j
public class WebSocketServer {
    public static final Map<String,Session> sessionMap=new ConcurrentHashMap<>();
    @OnOpen
    public void onOpen(@PathParam("username") String username, Session session){
        sessionMap.put(username,session);
        log.info("数据来自"+username);
        log.info("连接创建初始化");

        for (Map.Entry<String,Session> entry:sessionMap.entrySet()) {
            System.out.println(entry);
        }
    }

    @OnMessage
    public void onMessage(Session session,String message) throws IOException, InterruptedException {
        log.info("接收到数据"+message);
        String[] split = message.split(":");
        sessionMap.get(split[0]).getBasicRemote().sendText(split[1]);
    }
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
    @OnClose
    public void onClose(){
        log.info("关闭连接");
    }
}


注释
websocket在线连接,小项目,笔记,websocket,spring boot,vue

测试结果
websocket在线连接,小项目,笔记,websocket,spring boot,vue


注意:每一个请求对应一个WebSocketServer对象,每次变动都会调用对象中指定的方法,例如:每个请求连接时都会触发一次@onOpen下的方法、每个请求发送数据都会调用一次@onMessage标识下的方法…

前端页面

创建一个vue项目,因为后面项目会用到。这里也可以不创建,只要有一个能够运行js的环境即可,最简单的方式就是创建一个.html页面然后在浏览器中打开

第一个测试 与服务器建立连接

创建一个ws对象,利用此对象可以向后端发送数据获取后端数据等。创建方式很简单,在创建时就会进行连接(是指执行到这里时,而不是指new出来后)

websocket在线连接,小项目,笔记,websocket,spring boot,vue
页面运行后,服务端会立即创建连接
websocket在线连接,小项目,笔记,websocket,spring boot,vue

第二个测试 在postman中的A向浏览中的C发送数据,C接收数据并打印到页面;

要在上文已经完成后端测试二的基础上

websocket在线连接,小项目,笔记,websocket,spring boot,vue
注意:onmessage是一直进行监听服务端发送过来的数据的

第三个测试 在测试二的基础上向postMan的A发送数据

利用wc对象的send(“xxx”)方法

<template>
    <div>
        {{receptionData}}
        <el-input size="mini" v-model="data"></el-input>
        <el-button @click="toSendMsg()">发送</el-button>
    </div>
</template>
<script>
export default {
    data(){
        return{
            data:'',
            ws:undefined,
            receptionData:undefined
        }
    },
    created(){
      this.ws= new WebSocket('ws://localhost:8080/wsserver/C');
        this.ws.onmessage=(msg)=>{
            this.receptionData=msg.data
        }
    },
    methods:{
        toSendMsg(){
           this.ws.send("A:cccccc")
        }
    }
}
</script>

测试结果:
websocket在线连接,小项目,笔记,websocket,spring boot,vue
注意:当前端网页完毕时,会自动触发后端的关闭处理

此外还有 sc.close()手动进行关闭的一些前端处理、 sc.onerror()出现异常的一些处理,用法与onmessage相同,都是为其赋值一个函数

在测试过程中发现:数据只能被消费一次,即有多个客户端进行连接时,只能有一个客户端接收到服务端的数据。因为不同的客户端连接就有不同的连接session。由于服务端的代码使用map存储,key为唯一标识,value为session。当一个用户在多个客户端登录时,map中相同的key的旧值会被最新的值覆盖,就出现只有最后打开的网页能接收到服务端的数据。



在线聊天系统开发

本系统为自己原创,基于HTTP协议(例如:登录、注册)与ws协议(例如:实时聊天)的混合开发,目的是熟练的使用ws协议,所以在其他方面较为省略,可能会有bug或不对的地方,还望指正

前端部分

前端使用vue和Element组价库(非必要),使用axios发送HTTP的请求,使用webScocket对象发送ws请求。

  1. 使用npm创建一个vue项目
  2. 下载Element-ui并在main.js文件中进行导入
  3. 下载axios,创建一个工具类去封装axios请求,然后在需要的页面中的js部分导入。
  4. 配置路由
  5. 删除无用页面
  6. 然后测试项目能否正常运行,element是否导入成功等

项目的vue项目初始化部分这里不再一一介绍。
登录样式布局

websocket在线连接,小项目,笔记,websocket,spring boot,vue

代码部分:

<template>
  <div class="wrapper">
    <div class="login_div">
   
        <span class="title"><h2> 在线聊天室</h2></span>
        <div class="form_div">
          <el-form ref="form" :model="form" label-width="80px">
            <el-form-item>
              <el-input v-model="form.name" size="mini" placeholder="输入姓名"></el-input>
          </el-form-item>
            <el-form-item>
              <el-input v-model="form.password" size="mini" placeholder="输入密码" type="password"></el-input>
            </el-form-item>
             <el-form-item>
              <a href="#" style="color:blue">还没有账号?点我去注册</a>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="submitForm()" size="small" style="width:100%">提交</el-button>
          </el-form-item>
        </el-form>
        </div>
    </div>
  </div>
</template>

<script>
import {login} from '../api/userApi'
export default {
 
  data() {
    return {
      form:{
        name:'',
        password:''

      },
      mock:{
      
      }
    }
  },
  methods: {
      submitForm(){
        login(this.form).then(res=>{
           
        })
      }
  }
   
}
</script>
<style scoped>
.wrapper {
  height: 100vh;
  background-image: linear-gradient(to bottom right, #FC466B, #3F5EFB);
  width: 100%;
  overflow: hidden;
  position: relative;
 
}
.login_div{
  width:500px;
  height: 300px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -70%);
  background-color:aliceblue;
  opacity:0.9;  
}
.title{
  text-align: center  ;
}
.form_div{
  margin-right: 100px;
  margin-top: 50px;
}
</style>

聊天页面布局
用css画一个渐变色的背景,然后在画出页面的整体布局
websocket在线连接,小项目,笔记,websocket,spring boot,vue

<template>
  <div style="min-height: 100vh" class="window_div">
      <div class="chat_div">
          <div class="chat_header">
            <span class="hrader_title">当前用户:xxx</span>
            <span class="hrader_friend">正在和xxx 聊天</span>
          </div>

          <div class="chat_left">
              <div class="message_div"></div>
               <div class="input_div"></div>
          </div>
          <div class="chat_right">
            <div class="friend_div">
              <div class="friend_list_title"></div>
              <div class="friend_list"></div>
            </div>
            <div class="sys_info_div">
              <div class="sys_info_title"></div>
              <div class="sys_info"></div>
            </div>
          </div>
      </div>
  <div>
    </div>
  </div>
</template>

<script>


export default {
}
</script>

<style scoped>
.window_div{
  background-image: linear-gradient(to bottom right, #b1b1c5, #3F5EFB);
  overflow: hidden;
  position: relative;
}
.chat_div{
  width: 60%;
  height: 65vh;
  border: 1px solid red;
  margin: 10vh auto;
}
.chat_header{
  display: flex;
  width: 100%;
  height: 10vh;
  border: 1px solid red;
}

.chat_left{
  width: 70%;
  height: 55vh;
  border: 1px solid red;
  float: left; 
}

.chat_right{
  width: 30%;
  height: 55vh;
  border: 1px solid red;
  float: right; 
}
.hrader_title{
  display: flexbox;
  line-height: 10vh;
  margin-left: 6%;
  color: white;
  width: 30%;
  border: 1px solid red;
}
.hrader_friend{
  display: inline-block;
  margin-top: 6vh;
  height: 2vh;
  color: white;
  width: 25%;

  font-size: 12px;
  border: 1px solid red;
}
.friend_list_title{
  width: 100%;
  height: 5vh;
  border: 1px solid red;
}
.friend_list{
  width: 100%;
  height: 20vh;
  border: 1px solid red;
}
.friend_div{
  width: 100%;
  height: 25vh;
  border: 1px solid black;
}
.sys_info_div{
  width: 100%;
  height: 30vh;
  border: 1px solid black;
}
.sys_info_title{
  width: 100%;
  height: 5vh;
  border: 1px solid red;
}
.sys_info{
  width: 100%;
  height: 25vh;
  border: 1px solid red;
}
.message_div{
  width: 100%;
  height: 40vh;
  border: 1px solid red;
}
.input_div{
  width: 100%;
  height: 15vh;
  border: 1px solid red;
}

</style>

去掉边线进行填充后
websocket在线连接,小项目,笔记,websocket,spring boot,vue

此时前端样式除了消息部分已经完成,剩下去调试后端


后端部分

设计功能:

  1. 登录
  2. 显示在线的用户列表
  3. 实时聊天
  4. 上线提醒、下线提醒

设计用户姓名要唯一

流程图

websocket在线连接,小项目,笔记,websocket,spring boot,vue

消息类型
用户之间发送的消息、用户上线通知消息、用户下线通知消息、好友列表消息、系统通知(一些错误等)

websocket在线连接,小项目,笔记,websocket,spring boot,vue

消息体
发送发、接收方、消息类型、消息内容
websocket在线连接,小项目,笔记,websocket,spring boot,vue

思路总结

  1. 怎样确保安全性?原本计划向http请求那样每次请求携带请求头在拦截器中进项校验,经过测试发现,http请求时因为每一次都是不同的连接,才需要每次进行校验。ws可以在创建连接时只校验一次。在登录时返回一个token,服务端使用一个map保存一个着token记录。在ws创建连接时携带此token,服务端从map中进行查找,根据是否找到判断此连接是否合法。
  2. 消息的发送方怎么确定?在发送消息时,在请求体中设置发送发 (可能不咋安全)
  3. 怎样将用户连接放入session的map中?在校验ws的token通过后,将查找到的用户姓名放入LocalThrad中,在放入sessionMap时,从LocalThread取出用户姓名作为key,值为此连接的session
  4. 初始化进行怎样的操作?在初始化时将连接放入session的map中,然后将朋友列表通过此session进行返回,因为此次代码中是使用name作为key的,所以只需要遍历session的map所有的key即可。然后向所有用户发送系统消息,该用户已经上线
  5. 怎样区分不同类型的消息?设置消息格式能将不同类型的消息进行区分,将系统消息,好友列表、好友消息采用统一格式进行发送。
  6. 在线朋友列表怎样更新?初始连接时由后端向此连接发送当前所有在线用户,后续由系统提示上下线时,由前端进行更新
  7. 出现异常和断开连接怎样处理?封装一个通知其他session,此用户已经下线的方法,在此方法中根据参数列表中的session,去sessionMap中根据值去查找key,将key作为消息,同时将消息类型设置为用户下线向其他session中发送。前端接收到用户下线类型的消息,进行提示,同时在 在线朋友列表中去除此name。

代码注释

后端核心代码:(由于篇幅太长,这里只做注释,详细代码已经上传到gitee中,可以自行访问查看)
websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue
到这里,后端所有功能都已经基本完成,只差前端接收不同类型的消息,并将其赋值后进行渲染

websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue
websocket在线连接,小项目,笔记,websocket,spring boot,vue
此处控制台测试发送消息、接收消息均已成功,接下来就是本次项目最让人头疼的消息显示

采用循环数组的方式,这种方式会和平常聊天习惯存在点差异,这个版本就不去改了
websocket在线连接,小项目,笔记,websocket,spring boot,vue
此外在线人员列表也采用同种方式
websocket在线连接,小项目,笔记,websocket,spring boot,vue

在线聊天1.0 版本到此完成

源码

完整源码已经上传到gitee中 请点击访问 https://gitee.com/wang-yongyan188/websocketchat.git
提示:因为ws创建请求的token存储在了localStorage中,所以同一个浏览器即使的登录不同的账号也是同一个用户,所以要使用不同的浏览器去测试。如果只测试后端,更推荐使用postman去测试
websocket在线连接,小项目,笔记,websocket,spring boot,vue

所有代码皆为原创,博客和代码共用了两天时间,任何错误欢迎提示,如果觉得还可以,就请点个赞吧。
此项目的是理解ws协议,并能够使用springboot实现两种协议的混合开发。
代码页面比较简陋、功能也不完善(注册需要手动去数据库添加,只能和在线用户聊天等),如果喜欢,后续会推出比如:添加好友、消息未读提示、群聊、消息保存等,进一步完善成为一个小项目。文章来源地址https://www.toymoban.com/news/detail-758338.html

到了这里,关于WebSocket协议理解并实现在线聊天的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于 SpringBoot+WebSocket 无DB实现在线聊天室(附源码)

    0.1 样例展示 0.2 源码地址 GitHub:https://github.com/ShiJieCloud/web-chat Gitee:https://gitee.com/suitbaby/web-chat GitCode:I’m Jie / web-chat · GitCode 1.1 HTTP 常用的 HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出

    2024年02月05日
    浏览(49)
  • 微信小程序 WebSocket 通信 —— 在线聊天

             * 源码已经上传到资源处,需要的话点击跳转下载 |  源码下载         在Node栏目就讲到了Socket通信的内容,使用Node实现Socke通信,还使用两个流行的WebSocket 库,ws 和 socket.io,在小程序中的WebSocket接口和HTML5的WebSocket基本相同,可以实现浏览器与服务器之间的

    2024年02月01日
    浏览(50)
  • 基于WebSocket的在线文字聊天室

    与Ajax不同,WebSocket可以使服务端主动向客户发送响应,本案例就是基于WebSocket的一个在线聊天室,不过功能比较简单,只能满足文字交流。演示如下。 案例学习于b站up主,链接 。这位up主讲的非常清楚,值得去学习。本文属于记录自我学习过程的文章。 项目目录下app.js 项

    2024年02月13日
    浏览(62)
  • 在线聊天室(Vue+Springboot+WebSocket)

    实现了一个简单的在线聊天室的前后端。前端用Vue实现,后端用Springboot实现。         在线聊天室的功能包括创建用户和显示在线用户列表、发送消息和显示消息列表、用户和消息列表实时更新这几点。以下是整体功能的活动图: 用户身份         进入聊天室的用户需

    2024年01月15日
    浏览(51)
  • 基于SpringBoot+Vue+WebSocket的在线聊天室

    WebSocket 是一种在 Web 应用程序中实现双向通信的协议。它提供了一种持久连接,允许客户端和服务器之间进行实时数据传输,而无需进行频繁的请求和响应。 相对于传统的 HTTP 请求-响应模式,WebSocket 在客户端和服务器之间建立起一条长久的双向通信通道。这意味着服务器可

    2024年01月16日
    浏览(71)
  • Gin+WebSocket实战——在线聊天室WebSocketDemo详细使用教程

    Github:https://github.com/palp1tate/WebsocketDemo 欢迎star!😎 利用 Gin + WebSocket 实现的在线聊天室 Demo 项目,支持加入/离开聊天室广播、给其他用户发送消息等。 进入项目根目录,执行命令 go run . 命令,结果如下: 可以看到们的 HTTP 服务已经启动成功并运行在了 8080 端口上。 接下

    2024年04月26日
    浏览(74)
  • 巧妙利用java实现在线聊天系统教程方法

    一、搭建服务器端 a)、创建ServerSocket对象绑定监听端口。 b)、通过accept()方法监听客户端的请求。 c)、建立连接后,通过输入输出流读取客户端发送的请求信息。 d)、通过输出流向客户端发送请求信息。 e)、关闭相关资源。 二、搭建客户器端 a)、创建Socket对象,指明需要连接

    2024年02月08日
    浏览(89)
  • 毕业设计——基于springboot的在线聊天系统设计与实现

    完整项目地址:https://download.csdn.net/download/lijunhcn/88430400 本项目是一套聊天系统,包括前台手机界面及后台分布式系统,基于SpringBoot+Netty+MUI+H5Plus+Nginx+FastDFS分布式文件系统搭建的聊天系统。 前端聊天系统包含首页门户登录注册、互信、通讯录、发现、我等模块,添加了扫一

    2024年02月03日
    浏览(46)
  • WPF+ASP.NET SignalR实现简易在线聊天功能

    在实际业务中,当后台数据发生变化,客户端能够实时的收到通知,而不是由用户主动的进行页面刷新才能查看,这将是一个非常人性化的设计。有没有那么一种场景,后台数据明明已经发生变化了,前台却因为没有及时刷新,而导致页面显示的数据与实际存在差异,从而造

    2024年02月07日
    浏览(44)
  • C语言实现--基于UDP的多人在线聊天室

    目录 实现功能 实现思想 实现代码(部分及详解) 服务端部分代码 客户端部分代码 实现效果 项目中出现的问题和解决方法 项目整体代码展示 代码优化思路 服务端代码 客户端代码 服务端可以同时连接多个客户端; 新的客户端连接服务端时,可以在服务端显示自己的名字并

    2024年02月04日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包