fix: iperf支持v2和v3的命令操作
This commit is contained in:
@@ -38,7 +38,8 @@ let state = reactive({
|
|||||||
/**ws数据 */
|
/**ws数据 */
|
||||||
data: {
|
data: {
|
||||||
command: '', // 命令字符串
|
command: '', // 命令字符串
|
||||||
client: true, // 服务端或客户端,默认服务端
|
version: 'V3', // 服务版本,默认V3
|
||||||
|
mode: 'client', // 服务端或客户端,默认服务端
|
||||||
// Server or Client
|
// Server or Client
|
||||||
port: 5201, // 服务端口
|
port: 5201, // 服务端口
|
||||||
interval: 1, // 每次报告之间的时间间隔,单位为秒
|
interval: 1, // 每次报告之间的时间间隔,单位为秒
|
||||||
@@ -50,11 +51,13 @@ let state = reactive({
|
|||||||
time: 10, // 以秒为单位的传输时间(默认为 10 秒)
|
time: 10, // 以秒为单位的传输时间(默认为 10 秒)
|
||||||
reverse: false, // 以反向模式运行(服务器发送,客户端接收)
|
reverse: false, // 以反向模式运行(服务器发送,客户端接收)
|
||||||
window: '300k', // 设置窗口大小/套接字缓冲区大小
|
window: '300k', // 设置窗口大小/套接字缓冲区大小
|
||||||
|
parallel: 1, // 运行的并行客户端流数量
|
||||||
|
bitrate: 0, // 以比特/秒为单位(0 表示无限制)
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
/**连接发送 */
|
/**连接发送 */
|
||||||
async function fnIPerf3() {
|
async function fnIPerf() {
|
||||||
const [neType, neId] = state.neType;
|
const [neType, neId] = state.neType;
|
||||||
if (!neType || !neId) {
|
if (!neType || !neId) {
|
||||||
message.warning({
|
message.warning({
|
||||||
@@ -77,14 +80,15 @@ async function fnIPerf3() {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state.initialized) {
|
// 软件版本检查
|
||||||
fnResend();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state.params.neType = neType;
|
state.params.neType = neType;
|
||||||
state.params.neId = neId;
|
state.params.neId = neId;
|
||||||
const resVersion = await iperfV({ neType, neId });
|
const resVersion = await iperfV({
|
||||||
|
neType,
|
||||||
|
neId,
|
||||||
|
version: state.data.version,
|
||||||
|
});
|
||||||
|
|
||||||
if (resVersion.code !== RESULT_CODE_SUCCESS) {
|
if (resVersion.code !== RESULT_CODE_SUCCESS) {
|
||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: t('common.tipTitle'),
|
title: t('common.tipTitle'),
|
||||||
@@ -95,15 +99,20 @@ async function fnIPerf3() {
|
|||||||
} else {
|
} else {
|
||||||
state.versionInfo = resVersion.data;
|
state.versionInfo = resVersion.data;
|
||||||
}
|
}
|
||||||
|
// 初始化的直接重发
|
||||||
|
if (state.initialized) {
|
||||||
|
fnResend();
|
||||||
|
return;
|
||||||
|
}
|
||||||
state.initialized = true;
|
state.initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**触发安装iperf3 */
|
/**触发安装iperf */
|
||||||
function fnInstall() {
|
function fnInstall() {
|
||||||
const key = 'iperfI';
|
const key = 'iperfI';
|
||||||
message.loading({ content: t('common.loading'), key });
|
message.loading({ content: t('common.loading'), key });
|
||||||
const { neType, neId } = state.params;
|
const { neType, neId } = state.params;
|
||||||
iperfI({ neType, neId }).then(res => {
|
iperfI({ neType, neId, version: state.data.version }).then(res => {
|
||||||
if (res.code === RESULT_CODE_SUCCESS) {
|
if (res.code === RESULT_CODE_SUCCESS) {
|
||||||
message.success({
|
message.success({
|
||||||
content: 'install success',
|
content: 'install success',
|
||||||
@@ -140,7 +149,7 @@ function fnResend() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const data = JSON.parse(JSON.stringify(state.data));
|
const data = JSON.parse(JSON.stringify(state.data));
|
||||||
if (state.dataType === 'options') data.command = '';
|
if (state.dataType === 'options') data.command = '';
|
||||||
toolTerminal.value.send('iperf3', data);
|
toolTerminal.value.send('iperf', data);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,6 +158,38 @@ function fnConnect() {
|
|||||||
fnResend();
|
fnResend();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**终端消息处理*/
|
||||||
|
function fnProcessMessage(data: string): string {
|
||||||
|
// 查找的开始输出标记
|
||||||
|
const parts: string[] = data.split('\u001b[?2004l\r');
|
||||||
|
if (parts.length > 0) {
|
||||||
|
if (parts[0].startsWith('^C') || parts[0].startsWith('\r')) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
let text = parts[parts.length - 1];
|
||||||
|
// 找到最后输出标记
|
||||||
|
let lestIndex = text.lastIndexOf('\u001b[?2004h\u001b]0;');
|
||||||
|
if (lestIndex !== -1) {
|
||||||
|
text = text.substring(0, lestIndex);
|
||||||
|
}
|
||||||
|
if (text === '' || text === '\r\n' || text.startsWith('^C')) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
// 是否还有最后输出标记
|
||||||
|
lestIndex = text.lastIndexOf('\u001b[?2004h');
|
||||||
|
if (lestIndex !== -1) {
|
||||||
|
text = text.substring(0, lestIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log({ parts, text });
|
||||||
|
if (parts[0].startsWith('iperf')) {
|
||||||
|
return parts[0] + '\r\n' + text;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/**终端消息监听*/
|
/**终端消息监听*/
|
||||||
function fnMessage(res: Record<string, any>) {
|
function fnMessage(res: Record<string, any>) {
|
||||||
const { code, requestId, data } = res;
|
const { code, requestId, data } = res;
|
||||||
@@ -162,6 +203,11 @@ function fnMessage(res: Record<string, any>) {
|
|||||||
state.running = false;
|
state.running = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
lestIndex = data.lastIndexOf('failed:');
|
||||||
|
if (lestIndex !== -1) {
|
||||||
|
state.running = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
lestIndex = data.lastIndexOf('iperf Done.');
|
lestIndex = data.lastIndexOf('iperf Done.');
|
||||||
if (lestIndex !== -1) {
|
if (lestIndex !== -1) {
|
||||||
state.running = false;
|
state.running = false;
|
||||||
@@ -231,7 +277,7 @@ onBeforeUnmount(() => {});
|
|||||||
<template #extra>
|
<template #extra>
|
||||||
<a-space :size="8">
|
<a-space :size="8">
|
||||||
<a-button
|
<a-button
|
||||||
@click.prevent="fnIPerf3()"
|
@click.prevent="fnIPerf()"
|
||||||
type="primary"
|
type="primary"
|
||||||
:loading="state.running"
|
:loading="state.running"
|
||||||
>
|
>
|
||||||
@@ -266,8 +312,38 @@ onBeforeUnmount(() => {});
|
|||||||
:label-wrap="true"
|
:label-wrap="true"
|
||||||
style="padding: 12px"
|
style="padding: 12px"
|
||||||
>
|
>
|
||||||
<a-divider orientation="left">Server or Client</a-divider>
|
<a-row :gutter="16">
|
||||||
<a-row>
|
<a-col :span="4" :offset="2">
|
||||||
|
<a-form-item label="Mode" name="mode">
|
||||||
|
<a-radio-group
|
||||||
|
v-model:value="state.data.mode"
|
||||||
|
:disabled="state.running"
|
||||||
|
button-style="solid"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<a-radio-button value="client">Client</a-radio-button>
|
||||||
|
<a-radio-button value="server">Server</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="4">
|
||||||
|
<a-form-item
|
||||||
|
label="Version"
|
||||||
|
name="version"
|
||||||
|
:label-col="{ span: 8 }"
|
||||||
|
:label-wrap="true"
|
||||||
|
>
|
||||||
|
<a-radio-group
|
||||||
|
v-model:value="state.data.version"
|
||||||
|
:disabled="state.running"
|
||||||
|
button-style="solid"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
<a-radio-button value="V2">V2</a-radio-button>
|
||||||
|
<a-radio-button value="V3">V3</a-radio-button>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
<a-col :lg="6" :md="6" :xs="12">
|
<a-col :lg="6" :md="6" :xs="12">
|
||||||
<a-form-item label="Port" name="port">
|
<a-form-item label="Port" name="port">
|
||||||
<a-input-number
|
<a-input-number
|
||||||
@@ -294,21 +370,14 @@ onBeforeUnmount(() => {});
|
|||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
<a-divider orientation="left">
|
|
||||||
<a-radio-group
|
<template v-if="state.data.mode === 'client'">
|
||||||
v-model:value="state.data.client"
|
|
||||||
:disabled="state.running"
|
|
||||||
>
|
|
||||||
<a-radio :value="true">Client</a-radio>
|
|
||||||
<a-radio :value="false">Server</a-radio>
|
|
||||||
</a-radio-group>
|
|
||||||
</a-divider>
|
|
||||||
<template v-if="state.data.client">
|
|
||||||
<a-form-item
|
<a-form-item
|
||||||
label="Host"
|
label="Host"
|
||||||
name="host"
|
name="host"
|
||||||
help="run in client mode, connecting to <host>"
|
help="run in client mode, connecting to <host>"
|
||||||
:label-col="{ span: 3 }"
|
:label-col="{ span: 3 }"
|
||||||
|
:wrapper-col="{ span: 9 }"
|
||||||
:label-wrap="true"
|
:label-wrap="true"
|
||||||
>
|
>
|
||||||
<a-input
|
<a-input
|
||||||
@@ -358,7 +427,20 @@ onBeforeUnmount(() => {});
|
|||||||
:placeholder="t('common.inputPlease')"
|
:placeholder="t('common.inputPlease')"
|
||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
:min="1"
|
:min="1"
|
||||||
:max="60"
|
></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="Parallel"
|
||||||
|
name="parallel"
|
||||||
|
help="number of parallel client streams to run"
|
||||||
|
>
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="state.data.parallel"
|
||||||
|
:disabled="state.running"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
style="width: 100%"
|
||||||
|
:min="1"
|
||||||
></a-input-number>
|
></a-input-number>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
@@ -376,6 +458,20 @@ onBeforeUnmount(() => {});
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
></a-input>
|
></a-input>
|
||||||
</a-form-item>
|
</a-form-item>
|
||||||
|
<a-form-item
|
||||||
|
label="Bitrate"
|
||||||
|
name="bitrate"
|
||||||
|
help="target bitrate in bits/sec (0 for unlimited)"
|
||||||
|
>
|
||||||
|
<a-input-number
|
||||||
|
v-model:value="state.data.bitrate"
|
||||||
|
:disabled="state.running"
|
||||||
|
allow-clear
|
||||||
|
:placeholder="t('common.inputPlease')"
|
||||||
|
style="width: 100%"
|
||||||
|
:min="1"
|
||||||
|
></a-input-number>
|
||||||
|
</a-form-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
</template>
|
</template>
|
||||||
@@ -397,17 +493,26 @@ onBeforeUnmount(() => {});
|
|||||||
|
|
||||||
<!-- command -->
|
<!-- command -->
|
||||||
<div v-else style="padding: 12px">
|
<div v-else style="padding: 12px">
|
||||||
<a-auto-complete
|
<a-input-group compact>
|
||||||
v-model:value="state.data.command"
|
<a-select
|
||||||
:disabled="state.running"
|
v-model:value="state.data.version"
|
||||||
:dropdown-match-select-width="500"
|
:disabled="state.running"
|
||||||
style="width: 100%"
|
>
|
||||||
>
|
<a-select-option value="V2">iperf</a-select-option>
|
||||||
<a-input
|
<a-select-option value="V3">iperf3</a-select-option>
|
||||||
addon-before="iperf3"
|
</a-select>
|
||||||
placeholder="Client: -c 172.5.16.100 -p 5201 or Server: -s -p 5201"
|
<a-auto-complete
|
||||||
|
v-model:value="state.data.command"
|
||||||
|
:disabled="state.running"
|
||||||
|
:options="[
|
||||||
|
{ value: '--help' },
|
||||||
|
{ value: '-c 172.5.16.100 -p 5201' },
|
||||||
|
{ value: '-s -p 5201' },
|
||||||
|
]"
|
||||||
|
style="width: 400px"
|
||||||
|
placeholder="client or server command"
|
||||||
/>
|
/>
|
||||||
</a-auto-complete>
|
</a-input-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 运行过程 -->
|
<!-- 运行过程 -->
|
||||||
@@ -415,12 +520,13 @@ onBeforeUnmount(() => {});
|
|||||||
v-if="state.initialized"
|
v-if="state.initialized"
|
||||||
ref="toolTerminal"
|
ref="toolTerminal"
|
||||||
:id="`V${Date.now()}`"
|
:id="`V${Date.now()}`"
|
||||||
prefix="iperf3"
|
prefix="iperf"
|
||||||
url="/tool/iperf/run"
|
url="/tool/iperf/run"
|
||||||
:ne-type="state.params.neType"
|
:ne-type="state.params.neType"
|
||||||
:ne-id="state.params.neId"
|
:ne-id="state.params.neId"
|
||||||
:rows="state.params.rows"
|
:rows="state.params.rows"
|
||||||
:cols="state.params.cols"
|
:cols="state.params.cols"
|
||||||
|
:process-messages="fnProcessMessage"
|
||||||
style="height: 400px"
|
style="height: 400px"
|
||||||
@connect="fnConnect"
|
@connect="fnConnect"
|
||||||
@message="fnMessage"
|
@message="fnMessage"
|
||||||
|
|||||||
Reference in New Issue
Block a user