A:增加Gzip压缩

This commit is contained in:
jimmy committed 2025-07-03 16:26:10 +08:00
1 parent 7d1d3d9220
commit e4c60ccf8d
6 files changed
+100 -48

No files matched your search

@@ -1,5 +1,7 @@
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO.Compression;
using System.Net.WebSockets; using System.Net.WebSockets;
using System.Text;
using System.Text.Json; using System.Text.Json;
using System.Web; using System.Web;
using Common.Logger; using Common.Logger;
@@ -114,6 +116,36 @@ public class WebSocketManager
} }
} }
/// <summary>
/// 压缩需要发送的数据
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
private static byte[] Compress(string json)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(json);
using var outputStream = new MemoryStream();
// leaveOpen: false,确保 DeflateStream 完全关闭时写入尾部
using (var deflate = new DeflateStream(outputStream, CompressionLevel.Fastest))
{
deflate.Write(inputBytes, 0, inputBytes.Length);
} // Dispose 在这里调用,确保数据写入完成
return outputStream.ToArray();
}
private static byte[] CompressGzip(string json)
{
byte[] inputBytes = Encoding.UTF8.GetBytes(json);
using var outputStream = new MemoryStream();
using (var gzip = new GZipStream(outputStream, CompressionLevel.Fastest))
{
gzip.Write(inputBytes, 0, inputBytes.Length);
}
return outputStream.ToArray();
}
// 停止服务器 // 停止服务器
public void Stop() public void Stop()
{ {
@@ -159,7 +191,7 @@ public class WebSocketManager
if (_connections.TryGetValue(socketId, out var connection)) if (_connections.TryGetValue(socketId, out var connection))
{ {
connection.Socket.Close(); connection.Socket.Close();
// OnConnectionClose会被自动调用,但我们可以在这里预先记录关闭原因 // OnConnectionClose会被自动调用,但我们可以在这里预先记录关闭原因
Log.Information($"主动关闭连接: {socketId}, 原因: {reason}"); Log.Information($"主动关闭连接: {socketId}, 原因: {reason}");
} }
@@ -247,7 +279,7 @@ public class WebSocketManager
{ {
_connections.TryRemove(socket.ConnectionInfo.Id, out var conn); _connections.TryRemove(socket.ConnectionInfo.Id, out var conn);
string? uuid = null; string? uuid = null;
if (conn?.Uuid != null) if (conn?.Uuid != null)
{ {
uuid = conn.Uuid; uuid = conn.Uuid;
@@ -328,7 +360,7 @@ public class WebSocketManager
try try
{ {
var json = JsonHelper.ToJson(message); var json = JsonHelper.ToJson(message);
await socket.Socket.Send(json); await socket.Socket.Send(CompressGzip(json));
return true; return true;
} }
catch (Exception ex) catch (Exception ex)
@@ -370,7 +402,7 @@ public class WebSocketManager
foreach (var connection in _connections.Values) foreach (var connection in _connections.Values)
{ {
tasks.Add(connection.Socket.Send(json)); tasks.Add(connection.Socket.Send(CompressGzip(json)));
} }
try try
@@ -405,11 +437,12 @@ public class WebSocketManager
/// </summary> /// </summary>
public ClientConnection? GetConnection(string uuid) public ClientConnection? GetConnection(string uuid)
{ {
if (_uuidToSocketId.TryGetValue(uuid, out var socketId) && if (_uuidToSocketId.TryGetValue(uuid, out var socketId) &&
_connections.TryGetValue(socketId, out var connection)) _connections.TryGetValue(socketId, out var connection))
{ {
return connection; return connection;
} }
return null; return null;
} }
@@ -491,14 +524,14 @@ public static class WebSocketManagerUsageExample
public static void Initialize() public static void Initialize()
{ {
var wsManager = WebSocketManager.Instance; var wsManager = WebSocketManager.Instance;
// 订阅连接关闭事件 // 订阅连接关闭事件
wsManager.SubscribeConnectionClosed(OnConnectionClosed); wsManager.SubscribeConnectionClosed(OnConnectionClosed);
// 启动服务器 // 启动服务器
wsManager.Start(); wsManager.Start();
} }
private static void OnConnectionClosed(ConnectionClosedEventArgs args) private static void OnConnectionClosed(ConnectionClosedEventArgs args)
{ {
Console.WriteLine($"连接已关闭:"); Console.WriteLine($"连接已关闭:");
@@ -506,20 +539,20 @@ public static class WebSocketManagerUsageExample
Console.WriteLine($" UUID: {args.Uuid ?? "未知"}"); Console.WriteLine($" UUID: {args.Uuid ?? "未知"}");
Console.WriteLine($" 关闭时间: {args.ClosedAt}"); Console.WriteLine($" 关闭时间: {args.ClosedAt}");
Console.WriteLine($" 关闭原因: {args.Reason ?? "未知"}"); Console.WriteLine($" 关闭原因: {args.Reason ?? "未知"}");
// 在这里可以执行清理逻辑,比如: // 在这里可以执行清理逻辑,比如:
// - 清理用户相关的缓存数据 // - 清理用户相关的缓存数据
// - 更新用户在线状态 // - 更新用户在线状态
// - 记录用户离线时间 // - 记录用户离线时间
// - 通知其他相关服务 // - 通知其他相关服务
// 示例:清理用户数据 // 示例:清理用户数据
if (!string.IsNullOrEmpty(args.Uuid)) if (!string.IsNullOrEmpty(args.Uuid))
{ {
CleanupUserData(args.Uuid); CleanupUserData(args.Uuid);
} }
} }
private static void CleanupUserData(string uuid) private static void CleanupUserData(string uuid)
{ {
// 实现用户数据清理逻辑 // 实现用户数据清理逻辑
+1
View File
@@ -17,6 +17,7 @@
"@vicons/ionicons5": "^0.13.0", "@vicons/ionicons5": "^0.13.0",
"axios": "^1.10.0", "axios": "^1.10.0",
"gsap": "^3.13.0", "gsap": "^3.13.0",
"pako": "^2.1.0",
"pinia": "^3.0.1", "pinia": "^3.0.1",
"unplugin-auto-import": "^19.3.0", "unplugin-auto-import": "^19.3.0",
"unplugin-vue-components": "^28.7.0", "unplugin-vue-components": "^28.7.0",
+8
View File
@@ -17,6 +17,9 @@ importers:
gsap: gsap:
specifier: ^3.13.0 specifier: ^3.13.0
version: 3.13.0 version: 3.13.0
pako:
specifier: ^2.1.0
version: 2.1.0
pinia: pinia:
specifier: ^3.0.1 specifier: ^3.0.1
version: 3.0.2(typescript@5.8.3)(vue@3.5.14(typescript@5.8.3)) version: 3.0.2(typescript@5.8.3)(vue@3.5.14(typescript@5.8.3))
@@ -1800,6 +1803,9 @@ packages:
package-json-from-dist@1.0.1: package-json-from-dist@1.0.1:
resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, tarball: https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz} resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==, tarball: https://registry.npmmirror.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz}
pako@2.1.0:
resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
parent-module@1.0.1: parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, tarball: https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz} resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==, tarball: https://registry.npmmirror.com/parent-module/-/parent-module-1.0.1.tgz}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -4133,6 +4139,8 @@ snapshots:
package-json-from-dist@1.0.1: {} package-json-from-dist@1.0.1: {}
pako@2.1.0: {}
parent-module@1.0.1: parent-module@1.0.1:
dependencies: dependencies:
callsites: 3.1.0 callsites: 3.1.0
+35 -33
View File
@@ -146,42 +146,44 @@ const getLayout = (route) => {
:theme-overrides="themeStore.themeOverrides" :theme-overrides="themeStore.themeOverrides"
:theme="themeStore.theme" :theme="themeStore.theme"
> >
<n-global-style /> <n-message-provider>
<n-global-style />
<!-- 可拖动的导航栏 --> <!-- 可拖动的导航栏 -->
<div <div
v-if="isShowGenerateRouter" v-if="isShowGenerateRouter"
ref="navRef" ref="navRef"
class="nav-container" class="nav-container"
:style="{ left: `${navPosition.x}px`, top: `${navPosition.y}px` }" :style="{ left: `${navPosition.x}px`, top: `${navPosition.y}px` }"
@mousedown="startDrag" @mousedown="startDrag"
> >
<div class="drag-handle"> <div class="drag-handle">
<span class="drag-icon">≡</span> <span class="drag-icon">≡</span>
</div>
<ul class="route-list">
<li v-for="(subRoute, index) in subRouteLists" :key="index" class="route-item">
<n-button
:type="isActive(subRoute.path) ? 'primary' : 'default'"
@click="listClickJump(subRoute)"
>
{{ subRoute.displayName }}
</n-button>
</li>
</ul>
</div> </div>
<ul class="route-list">
<li v-for="(subRoute, index) in subRouteLists" :key="index" class="route-item">
<n-button
:type="isActive(subRoute.path) ? 'primary' : 'default'"
@click="listClickJump(subRoute)"
>
{{ subRoute.displayName }}
</n-button>
</li>
</ul>
</div>
<!-- 展示主要内容 --> <!-- 展示主要内容 -->
<div class="main-content"> <div class="main-content">
<router-view v-slot="{ Component, route }"> <router-view v-slot="{ Component, route }">
<transition name="fade-slide" mode="out-in"> <transition name="fade-slide" mode="out-in">
<component :is="getLayout(route)"> <component :is="getLayout(route)">
<component :is="Component" /> <component :is="Component" />
</component> </component>
</transition> </transition>
</router-view> </router-view>
<!-- <network-connection-panel2/>--> <!-- <network-connection-panel2/>-->
</div> </div>
</n-message-provider>
</n-config-provider> </n-config-provider>
</template> </template>
+11 -3
View File
@@ -9,6 +9,7 @@ import CSharpBridgeV2 from '@/correspond/CSharpBridgeV2'
import { ref, Ref } from 'vue' import { ref, Ref } from 'vue'
import { logB } from '@/utils/logHelper/logUtils' import { logB } from '@/utils/logHelper/logUtils'
import { useUuidStore } from '@/stores/uuidStore' import { useUuidStore } from '@/stores/uuidStore'
import pako from "pako";
export class WebSocketManager { export class WebSocketManager {
private socket: WebSocket | null = null private socket: WebSocket | null = null
@@ -102,10 +103,17 @@ export class WebSocketManager {
this.startHeartbeat() this.startHeartbeat()
} }
this.socket.onmessage = (event) => { this.socket.onmessage = async (event) => {
try { try {
const message: WebSocketResponse = JSON.parse(event.data) const arrayBuffer: ArrayBuffer = event.data instanceof Blob
this.handleMessage(message) ? await event.data.arrayBuffer()
: event.data;
const uint8Array = new Uint8Array(arrayBuffer);
const decompressed = pako.inflate(uint8Array, { to: "string" });
const json = JSON.parse(decompressed);
this.handleMessage(json)
} catch (error) { } catch (error) {
console.error('Error parsing WebSocket message:', error) console.error('Error parsing WebSocket message:', error)
} }
@@ -97,7 +97,7 @@ onMounted(() => {
// 发送请求【请求订阅软件列表】 // 发送请求【请求订阅软件列表】
const subAppInfo: SubscriptionProcessInfo = { const subAppInfo: SubscriptionProcessInfo = {
subscriptionType: 'ProcessInfo', subscriptionType: 'ProcessInfo',
interval: 1000, interval: 400,
processIds: newValue1.processIds, processIds: newValue1.processIds,
} }