gemercheung 3 роки тому
батько
коміт
36928d6678

+ 7 - 6
package.json

@@ -1,6 +1,6 @@
 {
-  "name": "vite-electron-builder",
-  "description": "Secure boilerplate for Electron app based on Vite",
+  "name": "socket-benmark",
+  "description": "压力测试GUI",
   "private": true,
   "engines": {
     "node": ">=v16.13",
@@ -17,7 +17,7 @@
     "build:main": "cd ./packages/main && vite build",
     "build:preload": "cd ./packages/preload && vite build",
     "build:renderer": "cd ./packages/renderer && vite build",
-    "compile": "cross-env MODE=production npm run build && electron-builder build --config .electron-builder.config.js --dir --config.asar=false",
+    "compile": "cross-env MODE=production npm run build && electron-builder build --config .electron-builder.config.js --dir --config.asar=true",
     "test": "npm run test:main && npm run test:preload && npm run test:renderer && npm run test:e2e",
     "test:e2e": "vitest run",
     "test:main": "vitest run -r packages/main --passWithNoTests",
@@ -54,15 +54,16 @@
     "unplugin-auto-expose": "0.0.1",
     "vite": "3.0.0",
     "vitest": "0.18.0",
-    "vue-tsc": "0.38.4"
+    "vue-tsc": "0.38.4",
+    "electron-rebuild": "^3.2.8"
   },
   "dependencies": {
-    "electron-rebuild": "^3.2.8",
     "electron-updater": "5.0.5",
     "node-pty": "^0.10.1",
     "socket.io-client": "^4.5.1",
     "socket.io-msgpack-parser": "^3.0.1",
     "vue": "3.2.37",
-    "xterm": "^4.19.0"
+    "xterm": "^4.19.0",
+    "xterm-addon-fit": "^0.5.0"
   }
 }

+ 41 - 14
packages/main/src/mainWindow.ts

@@ -4,6 +4,7 @@ import { URL } from 'url';
 import * as pty from 'node-pty';
 import * as os from 'os';
 
+
 const shell = os.platform() === 'win32' ? 'powershell.exe' : 'bash';
 
 interface ProcessEnv { [key: string]: string; }
@@ -11,6 +12,9 @@ interface ProcessEnv { [key: string]: string; }
 async function createWindow() {
   const browserWindow = new BrowserWindow({
     show: false, // Use 'ready-to-show' event to show window
+    width: 750,
+    height: 600,
+    resizable: false,
     webPreferences: {
       webviewTag: false, // The webview tag is not recommended. Consider alternatives like iframe or Electron's BrowserView. https://www.electronjs.org/docs/latest/api/webview-tag#warning
       preload: join(__dirname, '../../preload/dist/index.cjs'),
@@ -25,24 +29,47 @@ async function createWindow() {
    */
   browserWindow.on('ready-to-show', () => {
     browserWindow?.show();
-
+    let ptyProcess: pty.IPty | undefined;
     if (import.meta.env.DEV) {
       browserWindow?.webContents.openDevTools();
     }
-    ipcMain.on('start-Benmark-test', () => {
-      console.log('hey');
+    ipcMain.on('start-Benmark-test', (_, data) => {
+      console.log('hey', data);
+      const { url, count, stop } = data;
+      if (stop) {
+        try {
+          if (ptyProcess) {
+            browserWindow.webContents.send('terminal.incomingData', 'kill process(0), 压力测试结束!!');
+            ptyProcess.kill();
+            console.log('kill process');
+          }
+        } catch (err) {
+          try {
+            if (ptyProcess) {
+              browserWindow.webContents.send('terminal.incomingData', 'ill process(0), 压力测试结束!!!');
+              ptyProcess.kill('SIGKILL');
+              console.log('kill process');
+            }
+          } catch (e) {
+            // couldn't kill the process
+          }
+        }
+      } else {
+        const BenmarkFilePath = join(__dirname, '../../main/src/test.mjs');
+        ptyProcess = pty.spawn(shell, [`node ${BenmarkFilePath}`, `${url}`, `${count}`], {
+          name: 'xterm-color',
+          cols: 80,
+          rows: 30,
+          cwd: process.env.HOME,
+          env: process.env as unknown as ProcessEnv,
+        });
+
+        ptyProcess.on('data', function (data) {
+          // console.log('data', data);
+          browserWindow.webContents.send('terminal.incomingData', data);
+        });
+      }
       // console.log('pty', pty);
-      const ptyProcess = pty.spawn(shell, [`node ${join(__dirname, '../../main/src/muti-client.mjs')}`], {
-        name: 'xterm-color',
-        cols: 80,
-        rows: 30,
-        cwd: process.env.HOME,
-        env: process.env as unknown as ProcessEnv,
-      });
-      ptyProcess.on('data', function (data) {
-        // console.log('data', data);
-        browserWindow.webContents.send('terminal.incomingData', data);
-      });
 
       // ptyProcess.write('ls\r');
       // ptyProcess.resize(100, 40);

+ 95 - 0
packages/main/src/test.mjs

@@ -0,0 +1,95 @@
+import { io } from "socket.io-client";
+import customParser from "socket.io-msgpack-parser";
+
+const url = process.argv[2];
+const count = process.argv[3];
+
+console.log("socket-info::url:config-->", url);
+console.log("socket-info::url:count-->", count);
+console.log("socket-info::start-->压力测试正在开始");
+const URL = url || process.env.URL;
+// http://zhang9394@zhangyupeng:face3d.4dage.com:7005/zhangyupeng/chatIM.git
+const MAX_CLIENTS = Number(count) || 500;
+const POLLING_PERCENTAGE = 0.05;
+const CLIENT_CREATION_INTERVAL_IN_MS = 10;
+const EMIT_INTERVAL_IN_MS = 1000;
+// wws://test-socket.4dkankan.com/watch
+let clientCount = 0;
+let lastReport = new Date().getTime();
+let packetsSinceLastReport = 0;
+let testSceneNum = "t-test";
+let roomId = "00001";
+let userLimitNum = 2000;
+let agentId = 0;
+
+const createAgent = () => {
+  agentId += 1;
+  const nickName = `test_name_${agentId}`;
+  const userId = `6666666${agentId}`;
+  const role = agentId === 1 ? "leader" : "customer";
+  createClient({ userId, nickName, from: "0", role: role });
+  createClient({ userId, nickName, from: "1", role: role });
+  createClient({ userId, nickName, from: "2", role: role });
+};
+
+const createClient = ({ userId, nickName, from, role }) => {
+  // for demonstration purposes, some clients stay stuck in HTTP long-polling
+
+  const socket = io(URL, {
+    path: "/fsl-node",
+    transport: ["websocket"],
+    parser: customParser,
+    query: {
+      userId: userId,
+      from: from || 2,
+      sceneNum: testSceneNum,
+      role: role,
+      nickName: nickName,
+      roomId: roomId,
+      voiceStatus: 0,
+      enableTalk: true,
+      isAuthMic: 0,
+      isAllowMic: 0,
+      userLimitNum,
+      myHeadUrl:
+        "http://downza.img.zz314.com/edu/pc/wlgj-1008/2016-06-23/64ec0888b15773e3ba5b5f744b9df16c.jpg",
+    },
+  });
+
+  setInterval(() => {
+    socket.emit("client to server event");
+  }, EMIT_INTERVAL_IN_MS);
+
+  socket.on("server to client event", () => {
+    packetsSinceLastReport++;
+  });
+
+  socket.on("disconnect", (reason) => {
+    console.log(`disconnect due to ${reason}`);
+  });
+
+  if (++clientCount < MAX_CLIENTS) {
+    setTimeout(createAgent, CLIENT_CREATION_INTERVAL_IN_MS);
+  }
+};
+
+createAgent();
+
+const printReport = () => {
+  const now = new Date().getTime();
+  const durationSinceLastReport = (now - lastReport) / 1000;
+  const packetsPerSeconds = (
+    packetsSinceLastReport / durationSinceLastReport
+  ).toFixed(2);
+
+  console.log(
+    `client count: ${clientCount} ; average packets received per second: ${packetsPerSeconds}`
+  );
+
+  packetsSinceLastReport = 0;
+  lastReport = now;
+};
+
+setInterval(printReport, 5000);
+
+// console.log("argv", process.argv);

+ 8 - 3
packages/preload/src/index.ts

@@ -6,11 +6,16 @@ export { sha256sum } from './nodeCrypto';
 export { versions } from './versions';
 
 
-import { contextBridge, ipcRenderer } from 'electron';
+import { ipcRenderer } from 'electron';
 
-contextBridge.exposeInMainWorld('ipc', {
+export const ipc = {
     send: (channel: string, data: unknown) => ipcRenderer.send(channel, data),
     on: (channel: string, fun: (event: Electron.IpcRendererEvent, ...args: any[]) => void) => ipcRenderer.on(channel, fun),
-});
+};
+
+// contextBridge.exposeInMainWorld('ipc', {
+//     send: (channel: string, data: unknown) => ipcRenderer.send(channel, data),
+//     on: (channel: string, fun: (event: Electron.IpcRendererEvent, ...args: any[]) => void) => ipcRenderer.on(channel, fun),
+// });
 
 

+ 55 - 20
packages/renderer/src/App.vue

@@ -1,28 +1,56 @@
 <script lang="ts" setup>
 import './app.css';
-// import { ipcRenderer } from "#preload";
+import { ipc } from '#preload';
 import { Terminal } from 'xterm';
-import { onMounted } from 'vue';
+import { onMounted, ref } from 'vue';
+import { FitAddon } from 'xterm-addon-fit';
 
 //
+const config = ref({
+  url: 'wss://test-socket.4dkankan.com',
+  count: 200,
+  isStart: false,
+});
+let terminal: Terminal | null;
 onMounted(() => {
-  const terminal = new Terminal();
+  terminal = new Terminal({
+    cursorBlink: false,
+  });
+  const fitAddon = new FitAddon();
+  terminal.loadAddon(fitAddon);
+
   const terminalContainer: HTMLElement | null =
     document.getElementById('terminal');
   if (terminalContainer) {
     terminal.open(terminalContainer);
+    fitAddon.fit();
     // console.log('ipcRenderer', window.ipc);
-    // window.ipc.on('terminal.incomingData', (event, data) => {
-    //   console.log('1111', data);
-    //   terminal.write(data);
-    // });
+    ipc.on('terminal.incomingData', (event, data) => {
+      console.log('1111', data);
+      if (terminal) terminal.write(data);
+    });
   }
 });
 
 // var shell = os.platform() === "win32" ? "powershell.exe" : "bash";
 
 function start() {
-  // window.ipc.send('start-Benmark-test');
+  config.value.isStart = true;
+  ipc.send('start-Benmark-test', {
+    url: config.value.url,
+    count: config.value.count,
+  });
+}
+function stop() {
+  config.value.isStart = false;
+  ipc.send('start-Benmark-test', {
+    stop: true,
+  });
+  setTimeout(() => {
+    if (terminal) {
+      terminal.clear();
+    }
+  }, 200);
 }
 </script>
 
@@ -30,26 +58,30 @@ function start() {
   <h2>Socket Benmark test</h2>
   <fieldset>
     <legend>配置信息</legend>
-    <figure><span class="label">socket地址URL:</span> <input></figure>
-    <figure><span class="label">测试人数:</span> <input></figure>
+    <figure>
+      <span class="label">socket地址URL:</span> <input v-model="config.url">
+    </figure>
+    <figure>
+      <span class="label">测试人数:</span> <input v-model="config.count">
+    </figure>
   </fieldset>
 
   <div class="btns">
-    <button
-      class="start"
-      @click="start"
+    <button
+      v-show="!config.isStart"
+      class="start"
+      @click="start"
     >
       开始测试
     </button>
-    <button class="end">
-      停止测试
+    <button
+      v-show="config.isStart"
+      class="end"
+      @click="stop"
+    >
+      停止测试
     </button>
   </div>
-
-  <p>
-    Edit
-    <code>packages/renderer/src/App.vue</code> to test hot module replacement.
-  </p>
   <div id="terminal" />
 </template>
 
@@ -71,6 +103,9 @@ fieldset .label {
   min-width: 120px;
   display: inline-block;
 }
+.btns {
+  margin-bottom: 15px;
+}
 .btns button {
   padding: 5px 10px;
   margin: 0 5px;

+ 4 - 0
packages/renderer/src/app.css

@@ -150,4 +150,8 @@
 .xterm-decoration-top {
     z-index: 2;
     position: relative;
+}
+#terminal{
+    max-height: 150px;
+    overflow: hidden;
 }

+ 5 - 0
yarn.lock

@@ -5468,6 +5468,11 @@ xmlhttprequest-ssl@~2.0.0:
   resolved "http://192.168.0.47:4873/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67"
   integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==
 
+xterm-addon-fit@^0.5.0:
+  version "0.5.0"
+  resolved "http://192.168.0.47:4873/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
+  integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
+
 xterm@^4.19.0:
   version "4.19.0"
   resolved "http://192.168.0.47:4873/xterm/-/xterm-4.19.0.tgz#c0f9d09cd61de1d658f43ca75f992197add9ef6d"