问题描述
因此,对于我正在学习的课程,我们正在使用Node.js和Dgram用Javascript编码UDP pinger。我们得到了以下任务:
为应用程序创建客户端代码。您的客户端应向目标UDP服务器发送10条ping消息。对于每条消息,您的客户应计算从发送包裹到收到响应的往返时间。如果一路上丢了包裹,客户也要处理。这应通过在发送每个数据包后让客户端等待1秒钟的响应来完成。如果未收到答复,则客户端应进行相应的日志记录(程序包丢失,无响应,超时等),并发送新的程序包以重试。但是,发送的软件包总数仍应仅为10。客户端还应计算丢失的软件包/未收到响应的百分比,并在关闭连接之前记录该百分比。
这是正确的做法,我认为是这样。我已经编码了一段时间了,我差不多要完成了,但是在使客户端发送程序包,等待响应然后采取相应措施方面存在问题。
到目前为止,我的代码所做的基本上是发送ping,并且在收到pong时,它将发送另一个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,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,messageBuffer.length,host,(error,bytes) => {
if (error) {
reject(error);
} else {
resolve(bytes);
}
})
});
}
async function sendMessages(messageCount,timeout) {
for(let messageIndex = 0; messageIndex < messageCount; messageIndex++) {
let message = createMessage();
await sendMessage(message,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);