| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- import debug from "debug"
- import net from 'node:net';
- const log = {
- app: debug('ip_monitor')
- };
- // IP 监控配置接口
- interface IPMonitorConfig {
- timeout?: number; // 超时时间(毫秒)
- retries?: number; // 重试次数
- interval?: number; // 监控间隔(毫秒)
- }
- // IP 监控结果接口
- export interface IPMonitorResult {
- success: boolean; // 是否成功
- responseTime?: number; // 响应时间(毫秒)
- packetLoss?: number; // 丢包率(百分比)
- error?: string; // 错误信息
- }
- // 默认配置
- const DEFAULT_CONFIG: IPMonitorConfig = {
- timeout: 1000,
- retries: 3,
- interval: 60000
- };
- // IP 监控类
- export class IPMonitor {
- private config: IPMonitorConfig;
- private monitoring: Map<string, number> = new Map();
- constructor(config: IPMonitorConfig = {}) {
- this.config = { ...DEFAULT_CONFIG, ...config };
- }
- // 开始监控指定 IP
- async startMonitor(ip: string, callback: (result: IPMonitorResult) => void) {
- if (this.monitoring.has(ip)) {
- log.app(`IP ${ip} 已经在监控中`);
- return;
- }
- const monitor = async () => {
- try {
- const result = await this.ping(ip);
- callback(result);
- } catch (error) {
- log.app(`监控 IP ${ip} 时发生错误:`, error);
- callback({
- success: false,
- error: error instanceof Error ? error.message : '未知错误'
- });
- }
- };
- // 立即执行一次
- await monitor();
- // 设置定时监控
- const interval = setInterval(monitor, this.config.interval);
- this.monitoring.set(ip, interval);
- log.app(`开始监控 IP: ${ip}`);
- }
- // 停止监控指定 IP
- stopMonitor(ip: string) {
- const interval = this.monitoring.get(ip);
- if (interval) {
- clearInterval(interval);
- this.monitoring.delete(ip);
- log.app(`停止监控 IP: ${ip}`);
- }
- }
- // 停止所有监控
- stopAll() {
- for (const [ip, interval] of this.monitoring) {
- clearInterval(interval);
- this.monitoring.delete(ip);
- }
- log.app('已停止所有 IP 监控');
- }
- // 执行 ping 操作
- private async ping(ip: string): Promise<IPMonitorResult> {
- const results: number[] = [];
- let successCount = 0;
- let totalTime = 0;
- for (let i = 0; i < this.config.retries!; i++) {
- try {
- const startTime = Date.now();
- const result = await this.tcpPing(ip);
- const endTime = Date.now();
-
- if (result) {
- const responseTime = endTime - startTime;
- results.push(responseTime);
- totalTime += responseTime;
- successCount++;
- }
- } catch (error) {
- log.app(`Ping 尝试 ${i + 1} 失败:`, error);
- }
- }
- // 计算平均响应时间和丢包率
- const avgResponseTime = successCount > 0 ? totalTime / successCount : undefined;
- const packetLoss = ((this.config.retries! - successCount) / this.config.retries!) * 100;
- return {
- success: successCount > 0,
- responseTime: avgResponseTime,
- packetLoss: packetLoss
- };
- }
- // TCP ping 实现
- private async tcpPing(ip: string): Promise<boolean> {
- return new Promise((resolve, reject) => {
- const socket = new net.Socket();
- let timeout = false;
- // 设置超时
- const timer = setTimeout(() => {
- timeout = true;
- socket.destroy();
- reject(new Error('连接超时'));
- }, this.config.timeout);
- socket.on('connect', () => {
- clearTimeout(timer);
- socket.destroy();
- resolve(true);
- });
- socket.on('error', (error) => {
- clearTimeout(timer);
- if (!timeout) {
- reject(error);
- }
- });
- // 尝试连接
- socket.connect(80, ip);
- });
- }
- }
- // 导出单例实例
- export const ipMonitor = new IPMonitor();
|