# **Лабораторна робота №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}/`); }); ``` ## Результати запиту Запуску сервера локально: ![](https://imgur.com/tmMXf6H.png) Запуску серверу в replit.com: ![](https://imgur.com/RhS8r0q.png) Запуску серверу в replit.com через мобільний інтернет: ![](https://imgur.com/fhAzpYk.png) ## Оцінка відстані до сервера Мінімальну RTT яка найближч до "чистого" часу поширення і затримки передачі без черг і обробки. Якщо припустити, що сигнал проходить через оптичне волокно зі швидкістю приблизно 200 000 км/с (швидкість світла з коефіцієнтом заломленя 1.5 для оптоволокна), тоді відстань до сервера можна оцінити за формулою Час мінімальної затримки RTT становить 141 мс. ![](https://imgur.com/3AX5mZD.png) ![](https://imgur.com/5irhU80.png) ## Результати отриманні від утиліти ping ![](https://imgur.com/i1FL6Y3.png) Маємо невелику різниця в показниках, що може пояснюватися різними маршрутами трафіку та тим, що ping використовує ICMP.