owned this note
owned this note
Published
Linked with GitHub
# **Комп'ютерні системи та мережі Екзаменаційнй лист №2**
[TOC]
## Прізвище Ім'я та по Батькові. Дата народження
Мулярчук Владислава Сергіївна, 17.05.2004

## Екзаменаційне запитання (4 б)
### 1 Як методами контролю навантаження вирішується задача максимізації актуальної пропускної спроможності каналу? Чи можна ці методи використовувати на вищому рівні стеку протоколів OSI, наприклад, на мові javascript в браузері та на сервері? Якщо можна, наведить можливі приклади використання! (2 бали) ##
### Відповідь ###
:::info
Методи контролю навантаження вирішують задачу максимізації актуальної пропускної спроможності каналу шляхом динамічного регулювання обсягу передаваних даних, щоб:
Уникати перевантаження в мережі (яке призводить до втрат пакетів і повторної передачі);
Підтримувати рівень передачі на межі максимально можливої пропускної здатності, без її перевищення.
використовують зворотний зв’язок для корекції темпу передавання (наприклад, сигнал ACK/NAK або таймаути).
Мета — утримувати потік даних на межі пропускної здатності каналу без перевищення.
Наприклад, TCP використовує алгоритми на кшталт:
Slow Start — поступово збільшує вікно передачі.
Congestion Avoidance (AIMD) — зменшує швидкість після втрат.
Cubic, BBR — сучасніші адаптивні алгоритми.
Чи можна це реалізувати на вищих рівнях стеку (наприклад, у JavaScript у браузері)?
У прикладному рівні, зокрема в JavaScript (у браузері) та на сервері, немає прямого доступу до транспортного рівня (TCP), але можна реалізувати власну логіку регулювання навантаження.
Можна контролювати AIMD у WebSocket-клієнті, щоб регулювати швидкість відправки повідомлень залежно від поточних умов мережі і завантаженості сервера. Також можливо реалізувати Admission Control у WebRTC-додатку, щоб не дозволяти встановлювати нові peer-з’єднання, якщо статистика CPU/пакетної втрати погіршується. DASH(Dynamic Adaptive Streaming over HTTP)/HLS (HTTP Live Streaming) у браузері для адаптивного розподілу ресурсів, AQM-подібне випадкове скидання запитів на сервері тощо.
1 Адаптивне завантаження (adaptive streaming)
Наприклад, веб-відео або WebRTC:
Клієнт динамічно підлаштовує якість (бітрейт) відео на основі пропускної здатності (наприклад, MediaSource, RTCPeerConnection).
Оцінка швидкості каналу базується на затримках, розмірі буфера, часі завантаження.
2 HTTP polling / fetch retry delay
Клієнт адаптує частоту запитів до сервера (наприклад, опитування API раз на 2, 5, 10 секунд залежно від навантаження або збоїв).
:::
### Як можна використовувати методи контролю навантаження для вирішення задач: 1) забезпечення нормального (неперевантаженого) стану роботи серверу, 2) справедливий поділ обчислювальних ресурсів серверу між кількома одночасно працючими клієнтами? Поясніть, який механізм дозволяє розв'язувати обидві ці задачі разом? Для яких обчислювальних задач можно використовувати ці методи? Як впливає обчислювальна складність задачі на вибір методів контролю навантаження серверу?(2 бали) ###
### Відповідь ###
:::info
Методи контролю навантаження (congestion/load control) на прикладному та системному рівнях є ключовими для стабільної, ефективної та справедливої роботи серверів. Нижче — відповіді на всі частини питання:
1) Забезпечення нормального (неперевантаженого) стану роботи серверу
Методи контролю навантаження дозволяють:
Виявляти перевантаження (черги запитів, високе CPU/пам’ять);
Обмежувати швидкість прийому/обробки запитів;
Розставляти пріоритети між задачами або запитами;
Відмовлятися від обробки частини запитів (graceful degradation), коли сервер досягає меж.
Приклади:
Rate limiting (запитів/сек на IP, токен-бакети тощо);
Drop queue або “reject on overload”;
Автоматичне масштабування (автошардінг, балансування навантаження).
2) Як забезпечити справедливий поділ ресурсів між клієнтами?
Це досягається через:
Квоти — кожен клієнт отримує фіксований ліміт ресурсів;
Пріоритетні черги — менш вимогливі або критичні клієнти отримують більше пріоритету;
Механізми “fair scheduling”
наприклад, Round-Robin, Weighted Fair Queueing.
Який механізм дозволяє вирішувати обидві задачі одночасно?
Механізм: керування чергами + розумний розподіл ресурсів (scheduler)
Наприклад:
Token bucket / Leaky bucket → обмежує швидкість запитів (нормалізує навантаження);
Weighted Fair Queuing (WFQ) → справедливо розподіляє ресурси;
Backpressure + Feedback → клієнтам повертається сигнал про завантаження (HTTP 429, затримка відповіді, WS ping/pong тощо), і вони знижують частоту запитів.
3) Для яких задач це актуально?
Методи контролю навантаження ефективні у:
API-сервісах (REST, GraphQL);
Потоковій передачі даних (відео, WebSocket);
Обчислювальних задачах (наприклад, AI-інференс, бази даних);
Передачі файлів (upload/download).
4) Як впливає складність задачі на вибір методів?
Обчислювальна складність Вплив на контроль навантаження
Низька (O(1) – O(log n)) Простий rate limiting або обмеження одночасних запитів достатнє.
Середня (O(n log n)) Потрібна пріоритезація задач, розклад за вагою або черги з таймаутами.
Висока (O(n²) і більше) Необхідне попереднє планування (наприклад, job-queue), відкладена обробка або відмова при перевантаженні.
Чим дорожча задача, тим жорсткіший контроль потрібен, щоб не “вбити” сервер кількома паралельними зверненнями.
:::
## Розрахункові екзаменаційні завдання (6 балів) ##
### 2.1 Час передачі даних (3 бали)
Вашу екзаменаційну фотографію необхідно передати від клієнта на сервер з мінімальною підсумковою затримкою через комунікаційну систему із трьома виділеними для Вас паралельними каналами.
Обчислите мінімальний час передачі фотографії в цій комунікаційній системі, якщо для передачі даних в кожному каналі використовується протокол зупинки та очікування і якщо Вам відомі: обсяг даних - розмір в байтах Вашої фотографії, максимальний розмір пакету передачи 2000 байт, дистанція між клієнтом та сервером M тисяч километрів (дистанція - це дліна каналів, M - це місяць Вашого народження), смуга пропускання першого каналу 1 Мбіт/c, смуга пропускання другого каналу 2 Мбіт/c, смуга пропускання третього каналу 3 Мбіт/c, та тип каналів – радіорелейний.
### Відповідь ###
:::info
Вхідні дані:
Розмір фото = 203 620 байт = 203620 × 8 = 1 628 960 біт
Максимальний розмір пакета = 2000 байт = 16 000 біт
Відстань M = 5 ⇒ 5000 км
Швидкість світла в радіорелейному каналі = $3 \times 10^5$ км/с
Відомо:
* Обсяг даних (розмір фотографії): 203 620 байт
* Максимальний розмір пакета: 2000 байт
* Дистанція між клієнтом та сервером: $M = 5$ тисяч кілометрів = $5 \times 10^6$ метрів
* Смуга пропускання каналів:
* Канал 1: $C_1 = 1$ Мбіт/с = $1 \times 10^6$ біт/с
* Канал 2: $C_2 = 2$ Мбіт/с = $2 \times 10^6$ біт/с
* Канал 3: $C_3 = 3$ Мбіт/с = $3 \times 10^6$ біт/с
* Тип каналу: Радіорелейний (швидкість поширення сигналу $v = 3 \times 10^8$ м/с)
Кожен пакет має розмір 2000 байт. Кількість пакетів:
Кількість пакетів= 2000/203620 =102
1. Час поширення сигналу ($T_p$):
$T_p = \frac{\text{відстань}}{\text{швидкість світла}} = \frac{5000 }{3 \times 10^5\text{ }} \approx 0.0167 \text{ с}$
$T_{RRT} = 2 \times T_P = 0{,}34$ c
2. Час передачі одного пакета ($T_{передачі}$):
Розмір пакета в бітах: $2000 \text{ байти} \times 8 \text{ біт/байт} = 16000 \text{ біт}$
* Канал 1: $T_{передачі, 1} = \frac{16000}{1 \times 10^6} = 0.016 \text{ с}$
* Канал 2: $T_{передачі, 2} = \frac{16000}{2 \times 10^6} = 0.008 \text{ с}$
* Канал 3: $T_{передачі, 3} = \frac{16000}{3 \times 10^6} \approx 0.00533 \text{ с}$
3. Час передачі одного пакета за протоколом "зупинки та очікування" ($T_{одного пакета}$):
$T_{одного пакета} = T_{передачі} + 2 \times T_p$
* Канал 1: $T_{одного пакета, 1} = 0.016 + 2 \times 0.0167 = 0.0493 \text{ с}$
* Канал 2: $T_{одного пакета, 2} = 0.008 + 2 \times 0.0167 = 0.0413 \text{ с}$
* Канал 3: $T_{одного пакета, 3} = 0.00533 + 2 \times 0.0167 = 0.03863 \text{ с}$
4. Пропускна здатність каналів:
Пропускна здатність кожного каналу:
$$
R_i = \frac{L}{T_i}
$$
де:
- $L = 2000$ байт — розмір кадру
- $T_i$ — час передачі через $i$-ий канал
$$
R_1 = \frac{2000}{0.076} \approx 26315.8\ \text{байт/с}
$$
$$
R_2 = \frac{2000}{0.068} \approx 29411.8\ \text{байт/с}
$$
$$
R_3 = \frac{2000}{0.06533} \approx 30612.2\ \text{байт/с}
$$
5.Загальна пропускна здатність та час передачі
Сумарна пропускна здатність:
$$
R_{tot} = R_1 + R_2 + R_3 \approx 86339.8\ \text{байт/с}
$$
Обʼєм переданих даних:
$$
S = 1 628 960 \ \text{байт}
$$
Загальний час передачі:
$$
T_{total} = \frac{S}{R_{tot}} = \frac{1 628 960}{86339.8} \approx 18.86\ \text{с}
$$
Висновок:
Мінімальний час передачі фотографії об'ємом 203 620 байтів через задану комунікаційну систему з трьома паралельними каналами, що використовують протокол зупинки та очікування, становить приблизно 1.970 секунди.
:::
### 2.2 Відносна затримка (3 бали)
Розробить метод обчислення аналога відносної затримки якщо в пункті 2.1 длини каналів будуть різні! Порівняйте її з відносною затримкою для більш ефективного протоколу. Як можна використовувати цей більш ефективний протокол на мові javascript в клієнт-серверних додатках?
### Відповідь ###
:::info
##
Вступ: задача
Потрібно передати фотографію з клієнта на сервер із мінімальною підсумковою затримкою через 3 паралельні канали з різною довжиною та пропускною здатністю, де використовується Stop-and-Wait протокол.
Відомі параметри:
Розмір фото: S = 203620 байт
Розмір пакета: L = 2000 байт = 16000 біт
Пропускні здатності:
Канал 1: R1 = 1 Мбіт/c
Канал 2: R2 = 2 Мбіт/c
Канал 3: R3 = 3 Мбіт/c
Довжини каналів:
d1, d2, d3 — різні
Тип каналів: радіорелейні (швидкість поширення сигналу $v = 3 \times 10^5$км/с)
Формула
$$
a_i = \frac{d_i \cdot R_i}{v \cdot L}
$$
Приклад розрахунку:
км
\begin{align*}
d_1 &= 4 \times 10^3 \, \text{км}, \quad R_1 = 1 \, \text{Мбіт/с} = 1 \times 10^6 \, \text{біт/с} \\
d_2 &= 5 \times 10^3 \, \text{км}, \quad R_2 = 2 \, \text{Мбіт/с} = 2 \times 10^6 \, \text{біт/с} \\
d_3 &= 6 \times 10^3 \, \text{км}, \quad R_3 = 3 \, \text{Мбіт/с} = 3 \times 10^6 \, \text{біт/с} \\
L &= 16000 \, \text{біт} \\
v &= 3 \times 10^5 \, \text{м/с}
\end{align*}
\begin{align*}
a_1 &= \frac{4 \times 10^3 \cdot 1 \times 10^6}{3 \times 10^5 \cdot 16000} = \frac{4 \times 10^{12}}{4.8 \times 10^{12}} = 0.833 \\
a_2 &= \frac{5 \times 10^3 \cdot 2 \times 10^6}{3 \times 10^5 \cdot 16000} = \frac{1 \times 10^{13}}{4.8 \times 10^{12}} = 2.08 \\
a_3 &= \frac{6 \times 10^3 \cdot 3 \times 10^6}{3 \times 10^5 \cdot 16000} = \frac{1.8 \times 10^{13}}{4.8 \times 10^{12}} = 3.75
\end{align*}
Порівняння з ефективним протоколом (Sliding Window)
Stop-and-Wait:
Продуктивність обмежена: після кожного пакету — очікування підтвердження (ACK):
Порівняння:
\begin{array}{|l|c|c|}
\hline
\textbf{Характеристика} & \textbf{Stop-and-Wait} & \textbf{Sliding Window} \\
\hline
\text{Витрата часу на ACK} & \text{Висока (1 ACK = 1 пакет)} & \text{Мінімальна} \\
\hline
\text{Швидкість передачі} & \text{Залежить від } a & \text{Майже максимальна} \\
\hline
\text{Реалізація в JS} & \text{Проста} & \text{Складніша (керування вікном)} \\
\hline
\text{Коли ефективний} & \text{Короткі затримки} & \text{Довгі затримки, великі файли} \\
\hline
\end{array}
:::
## 3. Екзаменаційне завдання на реалізацію (15 балів)
### 3.1 Час передачі даних для протоколу зупинки та очікування
Використовуючи протокол HTTP, метод GET та API fetch() побудувати клієнт-серверний додаток для сервера на хостінгу glitch.com або github codespace, що
передбачає час передачі даних для протоколу зупинки та очікування із заданим розміром кадру даних.
виконує емпіричну оцінку часу передачі даних для протоколу зупинки та очікування.
передбачає час передачі даних для протоколу HTTP.
виконує емпіричну оцінку часу передачі даних для протоколу HTTP.
Обсяг даних для передачі - не більш 64 Мбайт, дані - це фото, або аудіо, що Ви вибираєте на клієнтському компьютері.
Гарантуйте у коді можливість зміни розміру кадру та максимальний розмір кадру даних 2000 байт.
Обчислите приблизну затримку поширення між клієнтом та сервером як для Вашої реалізації протоколу зупинки та очікування для різних розмірів кадру, так і для протоколу HTTP.
Отримайте емпіричну оцінку затримки передавання кадру даних як для Вашої реалізації протоколу зупинки та очікування для різних розмірів кадру, так і для протоколу HTTP.
Отримайте емпіричну оцінку смуги пропускання каналу як для Вашої реалізації протоколу зупинки та очікування для різних розмірів кадру, так і для протоколу HTTP.
Порівняйте і зробить висновки
:::info
Задача передбачає створення клієнт-серверного додатка на платформі Glitch, що реалізує передачу даних за допомогою протоколу зупинки та очікування (Stop-and-Wait) та протоколу HTTP, з можливістю емпіричної оцінки часу передачі, затримки та смуги пропускання.
Налаштування сервера:
файл server.js для обробки запитів на завантаження файлів:
Використання бібліотек multer, express, cors, path
fs.promises — асинхронная работа с файловой системой. для обробки завантажень
```javascript=
// server.js – Node + Express (CommonJS)
const express = require('express');
const multer = require('multer');
const cors = require('cors');
const path = require('path');
const fs = require('fs').promises;
const app = express();nst app = express();
const port = process.env.PORT || 3000;
// Middleware
app.use(cоrs());p.use(cоrs());
app.use(express.json());
app.use(express.raw({ type: 'application/octet-stream', limit: '2kb' })); //middleware для прийому бінарних даних (наприклад, кадрів у протоколі Stop-and-Wait):
```
Створюється папка uploads
```javascript=
// Путь к папке uploads
const uploadsDir = path.join(__dirname, 'uploads');
// Создание папки uploads
(async () => {
try {
await fs.mkdir(uploadsDir, { recursive: true });
console.log('Папка "uploads" готова.');
} catch (error) {
console.error('Помилка створення папки uploads:', error);
}
})();
```
Файли зберігаються в uploads, з унікальною назвою (по часу). Обмеження — 64 МБ.
Якщо надходить заголовок X-Frame-Number, запит обробляється як кадр Stop-and-Wait.
Інакше — як звичайне HTTP-завантаження через multer.
```javascript=
/// Конфигурация Multer
const storage = multer.diskStorage({
destination: (_, __, cb) => cb(null, uploadsDir),
filename: (_, file, cb) => cb(null, `${Date.now()}${path.extname(file.originalname)}`)
});
const upload = multer({
storage,
limits: { fileSize: 64 * 1024 * 1024 } // 64MB
});
// Обработка POST /upload (Stop-and-Wait и обычный HTTP)
app.post('/upload', async (req, res) => {
const frameNumber = req.headers['x-frame-number'];
if (frameNumber !== undefined) {
console.log(`Отримано кадр ${frameNumber}, розмір ${req.body.length} байт`);
return res.json({ message: `Кадр ${frameNumber} успішно отримано!` });
}
upload.single('file')(req, res, (err) => {
if (err instanceof multer.MulterError) {
return res.status(400).json({ error: `Помилка Multer: ${err.message}` });
} else if (err) {
console.error('Помилка завантаження (HTTP):', err);
return res.status(500).json({ error: `Помилка сервера: ${err.message}` });
}
if (!req.file) {
return res.status(400).json({ error: 'Файл не надано.' });
}
res.json({ message: 'Файл успішно отримано та збережено!' });
});
});
```
HTML частина:
```html=
// HTML-интерфейс тестирования
app.get('/', (_, res) => {
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>Тестування передачі даних</title>
<style>
body { font-family: sans-serif; }
#results { margin-top: 20px; border: 1px solid #ccc; padding: 10px; }
.result-item { margin-bottom: 5px; }
</style>
</head>
<body>
<h1>Тестування передачі даних</h1>
<div>
<label for="fileInput">Виберіть файл (макс. 64 МБ):</label>
<input type="file" id="fileInput" accept="image/*, audio/*">
</div>
<div>
<label for="frameSize">Розмір кадру (байт, макс. 2000):</label>
<input type="number" id="frameSize" value="200" min="1" max="2000">
</div>
<button onclick="testStopAndWait()">Тестувати Stop-and-Wait</button>
<button onclick="testHTTP()">Тестувати HTTP</button>
<div id="results">
<h2>Результати:</h2>
</div>
```
Містить JavaScript-код, який виконується на стороні клієнта (у браузері). Він включає функції для надсилання окремих кадрів (sendFrame), імітації протоколу Stop-and-Wait (testStopAndWait), тестування звичайного HTTP завантаження (testHTTP), розрахунку та відображення метрик передачі (calculateAndDisplayMetrics) та отримання приблизної смуги пропускання (getApproximateBandwidth).
```javascript=
<script>
const serverUrl = ''; // URL буде поточний
const resultsDiv = document.getElementById('results');
////----------
async function sendFrame(url, frame, frameNumber) {
const startTime = performance.now();
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/octet-stream',
'X-Frame-Number': frameNumber
},
body: frame
});
const endTime = performance.now();
if (!response.ok) {
throw new Error('Помилка при надсиланні кадру ' + frameNumber + ': ' + response.status);
}
const data = await response.json();
return endTime - startTime;
} catch (error) {
console.error('Помилка при надсиланні кадру ' + frameNumber + ':', error);
return -1;
}
}
////----------
async function testStopAndWait() {
const fileInput = document.getElementById('fileInput');
const frameSizeInput = document.getElementById('frameSize');
const file = fileInput.files[0];
const frameSize = parseInt(frameSizeInput.value);
if (!file) {
alert('Будь ласка, виберіть файл.');
return;
}
if (file.size > 64 * 1024 * 1024) {
alert('Розмір файлу не повинен перевищувати 64 МБ.');
return;
}
if (isNaN(frameSize) || frameSize <= 0 || frameSize > 2000) {
alert('Будь ласка, введіть коректний розмір кадру (1-2000 байт).');
return;
}
resultsDiv.innerHTML += '<div class="result-item"><h3>Тестування Stop-and-Wait (розмір кадру: ' + frameSize + ' байт)</h3></div>';
const startTimeTotal = performance.now();
let totalTime = 0;
let frameNumber = 0;
const chunkSize = frameSize;
let offset = 0;
while (offset < file.size) {
const chunk = file.slice(offset, offset + chunkSize);
const arrayBuffer = await chunk.arrayBuffer();
const uint8Array = new Uint8Array(arrayBuffer);
const frameStartTime = performance.now();
const transferTime = await sendFrame('/upload', uint8Array, frameNumber++);
const frameEndTime = performance.now();
if (transferTime > 0) {
totalTime += transferTime;
resultsDiv.innerHTML += '<div class="result-item">Кадр ' + frameNumber + ': час передачі = ' + (transferTime / 1000).toFixed(3) + ' с</div>';
} else {
resultsDiv.innerHTML += '<div class="result-item">Помилка передачі кадру ' + frameNumber + '</div>';
break;
}
await new Promise(resolve => setTimeout(resolve, 50));
offset += chunkSize;
}
const endTimeTotal = performance.now();
const totalTransferTime = (endTimeTotal - startTimeTotal) / 1000;
resultsDiv.innerHTML += '<div class="result-item"><b>Загальний час передачі (Stop-and-Wait): ' + totalTransferTime.toFixed(3) + ' с</b></div>';
calculateAndDisplayMetrics('Stop-and-Wait', file.size, totalTransferTime, frameSize);
}
////----------
async function testHTTP() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) {
alert('Будь ласка, виберіть файл.');
return;
}
resultsDiv.innerHTML += '<div class="result-item"><h3>Тестування HTTP</h3></div>';
const startTime = performance.now();
try {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const endTime = performance.now();
const transferTime = (endTime - startTime) / 1000;
if (response.ok) {
const data = await response.json();
resultsDiv.innerHTML += '<div class="result-item">HTTP: час передачі = ' + transferTime.toFixed(3) + ' с</div>';
calculateAndDisplayMetrics('HTTP', file.size, transferTime);
} else {
const errorData = await response.json();
resultsDiv.innerHTML += '<div class="result-item">HTTP: помилка передачі - ' + response.status + ' ' + (errorData.error || '') + '</div>';
}
} catch (error) {
resultsDiv.innerHTML += '<div class="result-item">HTTP: помилка - ' + error + '</div>';
}
}
function calculateAndDisplayMetrics(protocol, dataSize, transferTime, frameSize = null) {
resultsDiv.innerHTML += '<div class="result-item"><h4>Метрики для ' + protocol + ':</h4></div>';
const approximatePropagationDelay = 0.05;
resultsDiv.innerHTML += '<div class="result-item">Приблизна затримка поширення: ' + approximatePropagationDelay.toFixed(3) + ' с</div>';
let transmissionDelay;
if (protocol === 'Stop-and-Wait' && frameSize) {
transmissionDelay = (frameSize * 8) / getApproximateBandwidth();
resultsDiv.innerHTML += '<div class="result-item">Приблизна затримка передавання кадру (Stop-and-Wait, ' + frameSize + ' байт): ' + (transmissionDelay).toFixed(6) + ' с</div>';
} else if (protocol === 'HTTP') {
transmissionDelay = transferTime;
resultsDiv.innerHTML += '<div class="result-item">Приблизна затримка передавання (HTTP): ' + transmissionDelay.toFixed(3) + ' с</div>';
}
if (protocol === 'HTTP') {
resultsDiv.innerHTML += '<div class="result-item">Емпірична оцінка затримки передавання (HTTP): ' + transferTime.toFixed(3) + ' с</div>';
}
const bandwidthMbps = (dataSize * 8) / (transferTime * 1000 * 1000);
resultsDiv.innerHTML += '<div class="result-item">Емпірична оцінка смуги пропускання: ' + bandwidthMbps.toFixed(2) + ' Мбіт/с</div>';
}
function getApproximateBandwidth() {
return 10 * 1024 * 1024;
}
</script>
```
Результати


Порівняння та висновки
\begin{array}{|l|c|c|}
\hline
\textbf{Характеристика} & \textbf{Stop-and-Wait} & \textbf{HTTP} \\
\hline
\text{Витрата часу на ACK} & \text{Висока (1 ACK = 1 пакет)} & \text{Мінімальна} \\
\hline
\text{Швидкість передачі} & \text{Залежить від } a & \text{Майже максимальна} \\
\hline
\text{Реалізація в JS} & \text{Проста} & \text{Складніша (керування вікном)} \\
\hline
\text{Коли ефективний} & \text{Короткі затримки} & \text{Довгі затримки, великі файли} \\
\hline
\end{array}
Висновок: Протокол Stop-and-Wait ефективний при коротких затримках, але його ефективність зменшується при збільшенні затримок. Протокол HTTP забезпечує високу швидкість передачі даних і є більш ефективним для великих файлів та мереж з високою затримкою.
## [ Посилання на розв'язання](*)
:::success
https://glitch.com/edit/#!/plausible-sprout-violin?path=server.js%3A222%3A0
:::
# [4. Питання (приклад)]()
:::danger
*Ваша програма не синхронізує клієнта із сервером. У ній немає тестування асиметрії каналу. Додайте у реалізацію код, який якось вирішує ці проблеми!*
:::
---
:::info
Відповідь....
:::