websocket 请求头报错 Provisional headers are shown 的解决方法

今日简单总结 websocket 使用过程中遇到的问题,主要从以下三个方面来分享:

1、前端部分 websocket 代码

2、使用 koa.js 实现后端 websocket 服务搭建

3、和后端 java Netty 库对接时遇到连接失败问题

一、前端部分 websocket 代码

<template>
  <div id="app">
    <div v-for="item in messages" :key="item.id">
      {{ item.value }}
    </div>
    <el-form :inline="true">
      <el-form-item label="消息:">
        <el-input v-model="newMessage" placeholder="请输入内容"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="sendMessage">发送</el-button>
      </el-form-item>
    </el-form>
    <router-view />
  </div>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      messages: [],
      newMessage: '',
      socket: null,
    };
  },

  created() {
    this.initializeWebSocketConnection();
  },
  beforeDestroy() {
    if (this.socket) {
      this.socket.close();
    }
  },
  methods: {
    initializeWebSocketConnection() {
      // 建立连接
      this.socket = new WebSocket('ws://localhost:8083');
      // 客户端向服务端发送消息
      this.socket.onopen = () => {
        this.socket.send(
          JSON.stringify({
            value: this.newMessage,
          })
        );
      };

      // 客户端接收服务端的消息
      this.socket.onmessage = (event) => {
        const res = JSON.parse(event.data);
        this.messages.push(res.data);
      };

      // 错误处理
      this.socket.onerror = (error) => {
        console.error('WebSocket Error:', error);
      };

      // 关闭
      this.socket.onclose = () => {
        console.log('WebSocket connection closed');
      };
    },

    sendMessage() {
      // 手动向服务端发送消息
      if (this.socket.readyState === WebSocket.OPEN) {
        this.socket.send(
          JSON.stringify({
            value: this.newMessage,
          })
        );
        this.newMessage = '';
      } else {
        console.error('Cannot send message, the socket is not open.');
      }
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

二、使用 koa.js 实现后端 websocket 服务搭建

// app.js
const Koa = require('koa');
const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');

const app = new Koa();
const wss = new WebSocket.Server({
  port: 8083,
});

// 存储所有连接的客户端
const clients = new Set();

wss.on('connection', (ws) => {
  // 新客户端连接时添加到clients集合中
  clients.add(ws);

  console.log('WebSocket connection opened');
  ws.on('message', (message) => {
    console.log('Received message from client:', message);
    try {
      console.log('clients::', clients);
      // 将接收到的字符串转换为JSON对象
      const data = JSON.parse(message);
      // 在此处处理接收到的JSON数据
      console.log('Received data:', data);

      const response = {
        status: '200',
        message: 'success',
        data: {
          id: uuidv4(),
          value: data.value,
        },
      };

      // 将响应的JSON对象转换为字符串并通过WebSocket发送
      ws.send(JSON.stringify(response));
    } catch (error) {
      console.error('Error parsing JSON:', error);
      // 如果解析失败,发送错误消息回客户端
      ws.send(JSON.stringify({ error: 'Invalid JSON format' }));
    }
  });

  ws.on('close', () => {
    // 客户端关闭连接时从clients集合中移除
    clients.delete(ws);
    console.log('WebSocket connection closed');
  });

  ws.on('error', (error) => {
    console.error('WebSocket error:', error);
  });
});

// 假设这个函数会在数据状态改变时被调用
function onDataStateChange(newData) {
  // 遍历所有客户端连接并发送消息
  for (const client of clients) {
    if (client.readyState === WebSocket.OPEN) {
      client.send(
        JSON.stringify({
          status: '200',
          message: 'success',
          data: {
            id: uuidv4(),
            value: '数据发生改变啦...',
          },
        })
      ); // 发送新数据到客户端
    }
  }
}

// 示例:模拟数据状态改变并推送消息
setTimeout(() => {
  const newData = { status: 'updated', value: 'New Value' };
  onDataStateChange(newData); // 模拟数据状态改变,并向所有客户端推送消息
}, 10000); // 5秒后模拟数据改变

app.use(async (ctx) => {
  ctx.body = 'Hello, Koa!';
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

三、和后端 java Netty 库对接时遇到连接失败问题

前端在 1、2 步骤的验证时,websocket 成功建立连接,消息可以正常发送,但是在和后端小伙伴联调时,请求头一直报 Provisional headers are shown 错误,如下图:

原因,后端 java 在使用 Netty 库创建 webSocket 通信时,未添加协议处理器,当后端添加完协议处理器后,前端在进行通信的时候,需要在加上这个前缀,如下图:

前端的修改,如下图:

解决之后的请求头:

可以在 Messages 中看到消息推送,当客户端和服务端建立连接之后,客户端可以向服务端发送消息,服务端也可以向客户端推送消息,实现即时通信功能。如下图:

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-04-22 07:46:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-22 07:46:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-22 07:46:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-22 07:46:02       20 阅读

热门阅读

  1. 区分stable diffusion中的通道数与张量维度

    2024-04-22 07:46:02       12 阅读
  2. Logback:SpringBoot 2.0 整合 Logback (kafaka es)

    2024-04-22 07:46:02       13 阅读
  3. 对象存储的详细介绍

    2024-04-22 07:46:02       13 阅读
  4. 宝塔面板MYSQL自动停止解决办法

    2024-04-22 07:46:02       16 阅读
  5. 实现 Android 设备屏幕录制的批处理脚本

    2024-04-22 07:46:02       11 阅读
  6. centos常见的命令

    2024-04-22 07:46:02       18 阅读