# **Лабораторна робота №1**
[TOC]
## Завдання до лаборатної роботи №1
1. Зробити клієнт-серверний додаток на мові javascript, використовуючи протокол HTTP, що тестує повний час подорожі запиту до сервера та назад (RTT) з обчисленням мінімального, максимального, медіанного та середнього часу RTT, середнього квадратичного відхилення та коефіцієнта асимметрії для частот запитів с клієнта до сервера 16Гц, 8Гц, 4Гц, 2Гц, 1Гц для розмірів клієнтських запитів 128, 256, 512, 1024, 2048 байт.
Результати представити у вигляді таблиць
2. Протестувати роботу Вашого клієнт-серверного додатку в персональній мережі (PAN) та у всесвітній мережі (WAN, наприклад, на хостінгах replit.com), а також з мобільних пристроїв.
3. Дати оцінку відстані до сервера та тих характеристик каналу клієнт-сервер, що можно отримати з ціх даних
4. Порівняти отримані дані с даними системної мережевої утіліти ping.
## Рішення
Створюємо сервер на https://replit.com/
Створимо index.html - HTML-сторінка, з таблицею resTable для результатів.
```html=
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lab1. RTT</title>
</head>
<style>
table, th, td {
border: 2px solid blue;
border-collapse: collapse;
}
th, td {
padding: 10px;
}
</style>
<body>
<h1>Lab 1. RTT Test</h1>
<table id="resTable">
<tr>
<th>Frequency (Hz)</th>
<th>Size (bytes)</th>
<th>Min RTT (ms)</th>
<th>Max RTT (ms)</th>
<th>Median RTT (ms)</th>
<th>Average RTT (ms)</th>
<th>StdDev (ms)</th>
<th>Skewness </th>
</tr>
</table>
<script src="script.js"></script>
</body>
</html>
```
script.js: клієнтська частина, що вимірює час відповіді та обчислює статистику
```javascript=
const freqs = [1, 2, 4, 8, 16];
const sizes = [128, 256, 512, 1024, 2048];
(async function start() {
for (let size of sizes) {
for (let freq of freqs) {
await process(freq, size);
}
}
})();
async function process(freq, size) {
const results = [];
const intervalMs = 1000 / freq;
for (let i = 0; i < 10; i++) {
const uuid = crypto.randomUUID();
const startTime = Date.now();
try {
const response = await fetch('/test', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
uniqueId: uuid,
data: Array(size).fill('W')
})
});
const rtt = Date.now() - startTime;
results.push(rtt);
const data = await response.json();
console.log(`Request ID: ${data.requestId}, RTT: ${rtt}ms`);
} catch (error) {
console.error('Request failed:', error);
}
await delay(intervalMs);
}
calculateAndShow(freq, size, results);
}
function calculateAndShow(freq, size, results) {
if (results.length === 0) {
const output = `
<tr>
<td>${freq}</td>
<td>${size}</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
<td>Unknown</td>
</tr>
`;
document.getElementById("resTable").innerHTML += output;
return;
}
const min = Math.min(...results);
const max = Math.max(...results);
const mean = results.reduce((sum, val) => sum + val, 0) / results.length;
const sorted = [...results].sort((a, b) => a - b);
const median = sorted[Math.floor(sorted.length / 2)];
const stdDev = Math.sqrt(results.reduce((sum, val) => sum + Math.pow(val - mean, 2), 0) / results.length);
const skewness = stdDev !== 0
? results.reduce((sum, val) => sum + Math.pow(val - mean, 3), 0) / (results.length * Math.pow(stdDev, 3))
: 0;
const output = `
<tr>
<td>${freq}</td>
<td>${size}</td>
<td>${min.toFixed(2)}</td>
<td>${max.toFixed(2)}</td>
<td>${median.toFixed(2)}</td>
<td>${mean.toFixed(2)}</td>
<td>${stdDev.toFixed(2)}</td>
<td>${skewness.toFixed(2)}</td>
</tr>
`;
document.getElementById("resTable").innerHTML += output;
}
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
```
server.js — серверна частина, яка обробляє запити та відправляє результати назад.
```javascript=
const http = require("http");
const fs = require("fs");
const path = require("path");
const PORT = 3000;
const server = http.createServer((req, res) => {
if (req.method === "GET" ) {
let filePath = req.url === "/" ? "index.html" : req.url;
let extname = path.extname(filePath);
let contentType = extname === ".js" ? "application/javascript" : "text/html";
fs.readFile(path.join(__dirname, filePath),
(err, data) => {
if (err) {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found");
} else {
res.writeHead(200, { "Content-Type": contentType });
res.end(data);
}
});
} else if (req.method === "POST" && req.url === "/test") {
let body = '';
req.on('data', chunk => { body += chunk; });
req.on('end',
() => {
try {
let requestData = JSON.parse(body);
let requestId = requestData.requestId;
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ requestId, status: "SUCCESS" }));
} catch (error) {
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ error: error.message }));
}
});
} else {
res.writeHead(404, { "Content-Type": "text/plain" });
res.end("Not Found");
}
});
server.listen(PORT, () => {
console.log(`Server running at http://localhost:${PORT}/`);
});
```
## Результати запиту
Запуску сервера локально:

Запуску серверу в replit.com:

Запуску серверу в replit.com через мобільний інтернет:

## Оцінка відстані до сервера
Мінімальну RTT яка найближч до "чистого" часу поширення і затримки передачі без черг і обробки.
Якщо припустити, що сигнал проходить через оптичне волокно зі швидкістю приблизно 200 000 км/с (швидкість світла з коефіцієнтом заломленя 1.5 для оптоволокна), тоді відстань до сервера можна оцінити за формулою
Час мінімальної затримки RTT становить 141 мс.


## Результати отриманні від утиліти ping

Маємо невелику різниця в показниках, що може пояснюватися різними маршрутами трафіку та тим, що ping використовує ICMP.