当前位置: 首页 > news >正文

netty启用websocket的压缩机制

netty启用websocket的压缩机制

package com.aerotop.connector.websocket.base;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.compression.JZlibDecoder;
import io.netty.handler.codec.compression.JZlibEncoder;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketServerCompressionHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * @author xhh
 */
public class WebSocketServerInitialzer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();
        //websocket 基于http协议,所以要有http编解码器
        pipeline.addLast(new HttpServerCodec());
        //对写大数据流的支持
        pipeline.addLast(new ChunkedWriteHandler());
        //对httpMessage进行聚合,聚合成fullHttpRequest或fullHttpRespones
        pipeline.addLast(new HttpObjectAggregator(1024 * 64));

        //支持websocket,并启用压缩,设置压缩子协议
        pipeline.addLast(new WebSocketServerProtocolHandler("/websocket", "permessage-deflate", true));
        // 添加压缩处理器
        pipeline.addLast(new WebSocketServerCompressionHandler());

        //自定义的handler
        pipeline.addLast(new NettyWebSocketHandler());
    }
}

前端vue,websocket启用压缩

<template>
  <div id="app-1">
    <!-- 输入框绑定message数据 -->
    <input 
      type="text" 
      v-model="message" 
      placeholder="输入消息"
      @keyup.enter="sendMessage"
    >
    <!-- 发送按钮 -->
    <button @click="sendMessage">发送</button>
    
    <!-- 消息展示区域 -->
    <div id="output">
        <!-- 遍历messages数组 -->
        <p v-for="(msg, index) in messages" :key="index">
            {{ msg }}
        </p>
    </div>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        message: '',       // 绑定输入框内容
        messages: [],      // 存储所有消息记录
        socket: null       // WebSocket实例
      };
    },
    mounted() {
        // 组件挂载后初始化WebSocket
        this.initWebSocket()
    },
    methods: {
        // 初始化WebSocket连接
        initWebSocket() {
            // 创建带压缩协商的WebSocket连接
            this.socket = new WebSocket('ws://127.0.0.1:8002/websocket', ['permessage-deflate'])
            
            // 连接成功回调
            this.socket.onopen = (event) => {
                this.log(`连接已建立,压缩支持:${this.socket.extensions}`)
            }
            
            // 接收消息回调
            this.socket.onmessage = (event) => {
                this.log(`收到消息: ${event.data}`)
            }
            
            // 错误处理
            this.socket.onerror = (error) => {
                debugger
                this.log('连接错误: ' + error)
            }
            
            // 连接关闭处理
            this.socket.onclose = (event) => {
                this.log('连接已关闭')
            }
        },
        
        // 发送消息方法
        sendMessage() {
            if (!this.message.trim()) return  // 空消息过滤
            
            if (this.socket.readyState === WebSocket.OPEN) {
                this.socket.send(this.message)
                this.log(`已发送: ${this.message}`)
                this.message = ''  // 清空输入框
            } else {
                this.log('连接未就绪')
            }
        },
        
        // 记录日志方法
        log(text) {
            this.messages.push(text)  // 自动触发视图更新
            
            // 自动滚动到底部(可选)
            const outputDiv = document.getElementById('output')
            if (outputDiv) {
                outputDiv.scrollTop = outputDiv.scrollHeight
            }
        }
    },
    beforeDestroy() {
        // 组件销毁前关闭连接
        if (this.socket) {
            this.socket.close()
        }
    }
  };
</script>


<style scoped>
/* 修改后的样式 */
#app {
  max-width: 600px;
  margin: 20px auto;
  padding: 20px;
  background: #2d3439;  /* 新增背景色 */
}

#output {
  margin-top: 20px;
  height: 900px;
  overflow-y: auto;
  border: 1px solid #3d4a52;  /* 调整边框颜色 */
  padding: 10px;
  background: #1e2327;  /* 深色背景 */
  border-radius: 8px;   /* 添加圆角 */
}

p {
  margin: 5px 0;
  padding: 8px 12px;
  color: #ffffff;       /* 白色文字 */
  background: #2d3439;  /* 消息背景 */
  border-radius: 4px;   /* 圆角效果 */
  border-bottom: 1px solid #3d4a52; /* 调整分割线 */
}

/* 滚动条样式 */
#output::-webkit-scrollbar {
  width: 8px;
}

#output::-webkit-scrollbar-track {
  background: #1e2327;
}

#output::-webkit-scrollbar-thumb {
  background: #3d4a52;
  border-radius: 4px;
}
</style>

相关文章:

  • 实现一个 Markdown 编辑器组件:Vue 3 + Vite + Highlight.js
  • java基础 关键字static
  • 导引头是个啥
  • 反射 tcp
  • DrissionPage移动端自动化:从H5到原生App的跨界测试
  • Linux: 线程控制
  • 企业官网的管理后台包含哪些功能模块详细
  • 本地项目提交到gitee
  • uboot启动过程中无法被打断和进入uboot命令行问题解决(基于2017.09版本uboot)
  • 若依前后端分离版本从mysql切换到postgresql数据库
  • [CISSP] [8] 安全模型,设计和能力的原则
  • Kubernetes 节点磁盘空间空了怎么办?解决 containerd overlay 100%问题
  • 如何创建单独的城市活码?活码能永久使用吗?
  • 理解JSON-RPC 2.0 协议
  • 力扣HOT100之链表:24. 两两交换链表中的节点
  • 1. Git 下载和安装
  • docker compose安装智能体平台N8N
  • 蓝桥杯嵌入式按键长按双击
  • 408 计算机网络 知识点记忆(5)
  • Go 微服务框架 | 中间件
  • 莱特币做空网站/最大的推广平台
  • 没网站可以做百度推广吗/广告收益平台
  • 如何做网站营销/长沙 建站优化
  • 如何使用电子商务网站/个人网站怎么建立
  • 企业形象网站开发/互动营销平台
  • 合肥营销型网站建设/网站长尾关键词排名软件