🎉 init: 小龙的工作空间
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@network-tool/shared-protocol",
|
||||
"version": "0.1.0",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"dev": "tsc --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@network-tool/shared-types": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"typescript": "^5.4.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
import type { NetworkMessage } from '@network-tool/shared-types';
|
||||
|
||||
/**
|
||||
* 消息帧格式:
|
||||
* ┌──────────────┬──────────────────┐
|
||||
* │ Header (4B) │ Payload (JSON) │
|
||||
* │ msg length │ UTF-8 bytes │
|
||||
* └──────────────┴──────────────────┘
|
||||
*/
|
||||
|
||||
export const PROTOCOL_VERSION = 1;
|
||||
export const FRAME_HEADER_SIZE = 4; // 4 bytes for length prefix
|
||||
|
||||
/**
|
||||
* 编码消息为网络传输格式
|
||||
*/
|
||||
export function encodeMessage(msg: NetworkMessage): Buffer {
|
||||
const json = JSON.stringify(msg);
|
||||
const payload = Buffer.from(json, 'utf-8');
|
||||
const header = Buffer.alloc(FRAME_HEADER_SIZE);
|
||||
header.writeUInt32BE(payload.length, 0);
|
||||
return Buffer.concat([header, payload]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码网络消息
|
||||
*/
|
||||
export function decodeMessage(data: Buffer): NetworkMessage {
|
||||
const json = data.toString('utf-8');
|
||||
return JSON.parse(json) as NetworkMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从流式数据中提取帧(处理粘包/拆包)
|
||||
*/
|
||||
export class FrameParser {
|
||||
private buffer: Buffer = Buffer.alloc(0);
|
||||
|
||||
push(chunk: Buffer): NetworkMessage[] {
|
||||
this.buffer = Buffer.concat([this.buffer, chunk]);
|
||||
const messages: NetworkMessage[] = [];
|
||||
|
||||
while (this.buffer.length >= FRAME_HEADER_SIZE) {
|
||||
const payloadLength = this.buffer.readUInt32BE(0);
|
||||
const totalLength = FRAME_HEADER_SIZE + payloadLength;
|
||||
|
||||
if (this.buffer.length < totalLength) {
|
||||
break; // 数据不完整,等待更多数据
|
||||
}
|
||||
|
||||
const payload = this.buffer.subarray(FRAME_HEADER_SIZE, totalLength);
|
||||
try {
|
||||
messages.push(decodeMessage(payload));
|
||||
} catch {
|
||||
// 跳过损坏的消息
|
||||
}
|
||||
this.buffer = this.buffer.subarray(totalLength);
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.buffer = Buffer.alloc(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
Reference in New Issue
Block a user