javascript dgram节点中的UDP Ping器超时



因此,对于我正在学习的一门课程,我们使用Node.js和Dgram在Javascript中编码UDP Ping器。我们接到了以下任务:

为应用程序创建客户端代码。您的客户端应该向目标UDP服务器发送10条ping消息。对于每条消息,您的客户应该计算从发送包到收到响应的往返时间。如果一个包被丢弃,客户端也要处理这个问题。这应该通过让客户端在发送每个包后等待1秒的响应来完成。如果没有收到回复,客户端应该相应地进行日志记录(包丢失、没有响应、超时等(,并发送一个新包重试。然而,发送的包裹总数仍然应该只有10个。客户端还应该计算丢失的包/未收到响应的包的百分比,并在连接关闭之前将其记录下来。

这似乎很直接,我也这么认为。我已经编码了一段时间,几乎完成了,但我在让客户发送包裹、等待响应,然后采取相应行动方面遇到了问题。

到目前为止,我的代码基本上是发送一个ping,当收到一个ping时,它会发送另一个ping。我不知道如何在发送下一个包之前记录未收到响应。换言之,我知道如何让它对收到的响应做出反应,只是不知道如果在规定的时间内没有做出响应,该如何让它做出反应。我试过使用if语句和循环以及异步函数,但我还没有让它发挥作用,所以现在我正在寻求帮助。

代码在这里:

const dgram = require("dgram");
const ms = require("ms"); 
var client = dgram.createSocket("udp4");

const PORT = 8000;
const HOST = "localhost";
let today = "";
let t0 = "";
let t1 = "";
let RTT = "";
let sentPackages = "";
let receivedPackages = "";
const messageOutbound = Buffer.from("You Up?");
sendPackage();
const x = setInterval(sendPackage, 1000);
client.on("message", (message, remote) => {
receivedPackages++
today = new Date();
t1 = today.getTime();
console.log(
`Message from: ${remote.address}:${remote.port} saying: ${message}`
);
RTT = ms(t1 - t0, { long: true });
console.log(RTT);
const x = setInterval(sendPackage, 1000);
});
client.on('error', (err) => {
console.log(`server error:n${err.stack}`);
server.close();
});  
async function sendPackage() {
if (sentPackages < 10) {
client.send(messageOutbound, 0, messageOutbound.length, PORT, HOST, () => {
sentPackages++
let today = new Date();
t0 = today.getTime();
console.log(
`message has been sent to ${HOST}:${PORT}. Message sent at: ${t0}`
);
});
} else {
calculateLoss();
client.close();
}
};
function calculateLoss() {
let amountLost =  sentPackages - receivedPackages;
let percentageLoss = amountLost / sentPackages * 100
console.log(amountLost);
console.log(percentageLoss +"% of packages lost");
};

我会使用async/await在消息之间等待1000ms/1s,然后跟踪数组中的所有消息。

我们用uuid来识别消息,这样我们就可以确保我们收到的消息与我们发送的消息相匹配。

然后我们可以记录所有需要的统计数据:

const dgram = require("dgram");
const uuid = require('uuid');
const PORT = 8000;
const HOST = "localhost";
const client = dgram.createSocket("udp4");
// Array that keeps track of the messages we send
let messages = [];
// When we get a message, decode it and update our message list accordingly...
client.on("message", (messageBuffer, remote) => {
let receivedMessage = bufferToMessage(messageBuffer);
// Find the message we sent and set the response time accordingly.
let message = messages.find(message => message.uuid === (receivedMessage ||{}).uuid);
if (message) {
message.responseTimestamp = new Date().getTime();
}
});
client.on('error', (err) => {
console.log(`server error:n${err.stack}`);
server.close();
});  
function createMessage() {
return { uuid: uuid.v4() };
}
function messageToBuffer(message) {
return Buffer.from(JSON.stringify(message), "utf-8");
}
function bufferToMessage(buffer) {
try {
return JSON.parse(buffer.toString("utf-8"));
} catch (error) {
return null;
}
}
// Wait for timeout milliseconds
function wait(timeout) {
return new Promise(resolve => setTimeout(resolve, timeout));
}
function sendMessage(message, port, host) {
// Save the messages to our list...
messages.push(message);
console.log(`Sending message #${messages.length}...`);
// Set the time we send out message...
message.sentTimestamp = new Date().getTime();
let messageBuffer = messageToBuffer(message);
return new Promise((resolve, reject) => {
client.send(messageBuffer, 0, messageBuffer.length, port, host, (error, bytes) => {
if (error) {
reject(error);
} else {
resolve(bytes);
}
})
});      
}
async function sendMessages(messageCount, port, host, timeout) {
for(let messageIndex = 0; messageIndex < messageCount; messageIndex++) {
let message = createMessage();
await sendMessage(message, port, host);
await wait(timeout);
if (message.responseTimestamp) {
console.log(`Response received after ${message.responseTimestamp - message.sentTimestamp} ms...`);
} else {
console.log(`No response received after ${timeout} ms...`);
}
}
logStatistics(messages);
}
function logStatistics(messages) {
let messagesSent = messages.length;
let messagesReceived = messages.filter(m => m.responseTimestamp).length;
let messagesLost = messagesSent - messagesReceived;
console.log(`Total messages sent: ${messagesSent}`);
console.log(`Total messages received: ${messagesReceived}`);
console.log(`Total messages lost: ${messagesLost} / ${(100*messagesLost / (messages.length || 1) ).toFixed(2)}%`);
if (messagesReceived > 0) {
console.log(`Average response interval:`, messages.filter(m => m.responseTimestamp).reduce((averageTime, message) =>  {
averageTime += (message.responseTimestamp - message.sentTimestamp) / messagesReceived;
return averageTime;
}, 0) + " ms");
}
}
sendMessages(10, PORT, HOST, 1000);

最新更新