Files
svn/tech/client/交接文档/谭健交接文档/Script/LogServer/Server.ts
2025-08-04 10:46:00 +08:00

116 lines
4.3 KiB
TypeScript

import randomName from 'chinese-random-name';
import fs from 'fs';
import path from 'path';
import WebSocket from 'ws';
import { Config, Error, HandlerConfig, Log, Protocol, ProtocolError, ProtocolInit, ProtocolLogs } from './type';
export enum LogLevel {
Log = 1, Warn = 2, Error = 3
}
export interface Handler {
onServerStart(): void;
onServerStop(): void;
onClientConnected(id: string): void;
onClientDisconnect(id: string): void;
onClientLogMessage(id: string, logs: Log[]): void;
onClientErrorMessage(id: string, error: Error): void;
}
export class Server {
private readonly logHandler: Handler[];
private readonly port: number = null;
private webSocketServer: WebSocket.Server = null;
constructor() {
const config: Config = JSON.parse(fs.readFileSync(path.join(__dirname, 'config', 'config.json')).toString());
this.port = config.port;
this.logHandler = [];
for (const handlerConfig of config.handlers) {
const handlerModule: any = require(`./handler/${handlerConfig.name}/${handlerConfig.name}`);
const handlerClass = handlerModule[handlerConfig.name] || handlerModule['default'];
this.logHandler.push(new handlerClass(handlerConfig));
}
}
public start(): void {
if (this.webSocketServer) {
return;
}
this.logHandler.forEach(handler => handler.onServerStart());
this.webSocketServer = new WebSocket.Server({ port: this.port, host: '0.0.0.0' });
this.webSocketServer.on('connection', (ws: WebSocket) => this.handleClient(ws));
}
public stop(): void {
this.logHandler.forEach(handler => handler.onServerStop());
this.webSocketServer && this.webSocketServer.close();
this.webSocketServer = null;
}
private genClientID(): string {
return randomName.generate();
}
private handleClient(ws: WebSocket): Promise<void> {
const promise: Promise<void> = new Promise((resolve: () => void) => {
let clientID: string = null;
let isClosed: boolean = false;
const handlerMessage = (message: string | any): void => {
if (!message) return;
if (typeof message !== 'string') message = message.toString();
let data: Protocol = null;
try { data = JSON.parse(message); } catch (error) { data = null };
if (!data) return;
switch (data.type) {
case 'init':
let initData: ProtocolInit = null;
try { initData = JSON.parse(data.data) } catch (error) { initData = null };
if (!initData) break;
clientID = initData.id || this.genClientID();
this.logHandler.forEach(handler => handler.onClientConnected(clientID));
ws.send(clientID);
break;
case 'log':
if (!clientID) break;
let logData: ProtocolLogs = null;
try { logData = JSON.parse(data.data); } catch (error) { logData = null };
if (!logData || !logData.logs) break;
this.logHandler.forEach(handler => handler.onClientLogMessage(clientID, logData.logs));
break;
case 'error':
if (!clientID) break;
let errorData: ProtocolError = null;
try { errorData = JSON.parse(data.data); } catch (error) { errorData = null };
if (!errorData || !errorData.error) break;
this.logHandler.forEach(handler => handler.onClientErrorMessage(clientID, errorData.error));
break;
}
}
const onClose = (): void => {
if (isClosed) return;
isClosed = true;
clientID && this.logHandler.forEach(handler => handler.onClientDisconnect(clientID));
resolve()
}
ws.on('message', (message: string) => handlerMessage(message));
ws.on('close', () => onClose());
ws.on('error', () => onClose());
});
return promise;
}
}
new Server().start();