[TOC]
# РГЗ
## Task Overview
Створити мульти-клієнт-серверний додаток з візуалізацією поточної топології мережі та стану з'єднань, що використовує хостинг replit.com
з реалізацією функціоналу за допомогою API Socket.IO
Додаток має забезпечувати
1) передачу повідомлень від вашого клієнта будь-якому іншому ([unicasting](https://en.wikipedia.org/wiki/Unicast))
2) передачу повідомлень від вашого клієнта всім іншим ([broadcasting](https://en.wikipedia.org/wiki/Broadcast,_unknown-unicast_and_multicast_traffic))
Повідомлення мають бути двох типів
* текстові повідомлення
* зображення
Під час передачі даних додаток повинен контролювати поточну [затримку поширення (propagation delay)](https://hackmd.io/y40T210qQ5-2pqQYJ6j09A#:~:text=%D0%97%D0%B0%D1%82%D1%80%D0%B8%D0%BC%D0%BA%D0%B0%20%D0%BF%D0%BE%D1%88%D0%B8%D1%80%D0%B5%D0%BD%D0%BD%D1%8F%20%E2%80%93,)) від клієнта $\delta_{i}$ і пропускну здатність $B_{i}$ канала клієнта (де $i$ - номер клієнта, що бере участь у поточній комунікації) та візуалізувати їх на діаграмі товщиною ребер графа діаграми та розміром вузлів.
## Загальна інформація
**Пропускна здатність:** Пропускна здатність (англ. bandwidth) відноситься до максимальної швидкості передачі даних через мережу або канал зв'язку. Зазвичай вимірюється у бітах на секунду (біт/с). Більша пропускна здатність дозволяє швидшу передачу даних і може підтримувати більше одночасних підключень або вищі обсяги даних.
**Затримка поширення:** Затримка поширення (англ. propagation delay) - це час, який потрібно сигналу для подорожі від відправника до одержувача в комунікаційному каналі. Вона включає час, необхідний для поширення сигналу через середовище (наприклад, кабелі, оптоволокно), а також будь-які затримки обробки в маршрутизаторах або комутаторах на шляху. Затримка поширення залежить від фізичної відстані між відправником та одержувачем, швидкості світла в середовищі та обчислювальних можливостей проміжних пристроїв.
## Багатоклієнтно-серверний додаток для візуалізації мережевої топології.
### Тестове середовище:
Для тестування додатку використовувався браузер з віртуальною приватною мережею (VPN) для симуляції різних мережевих умов і географічних розташувань.
### Огляд додатку
Додаток викладено на хостинг [repl.it](https://replit.com/join/fsaoogleao-alinayezhkova). Кількість клієнтів регулюється кількістю вкладок браузера. Використовується Firefox. Зовнішній вигляд додатку наступний:

Тут бачимо в логах 7 під'єднаних клієнтів. Не використовуючи VPN, маємо адреси
```
IP of user 0: 78.26.151.245, 10.82.32.16
IP of user 1: 78.26.151.245, 10.82.14.118
IP of user 2: 78.26.151.245, 10.82.32.11
IP of user 3: 78.26.151.245, 10.82.23.12
IP of user 4: 78.26.151.245, 10.82.45.15
IP of user 5: 78.26.151.245, 10.82.23.14
```
Включаючи VPN, отримаємо нову адресу
```
IP of user 6: 67.159.8.147, 10.82.25.12
```
Перша частина представляє собою зовнішню IP-адресу користувача. Зовнішні IP-адреси використовуються для ідентифікації пристроїв в Інтернеті. Друга частина є внутрішньою IP-адресою користувача. Внутрішні IP-адреси використовуються для ідентифікації пристроїв у локальній мережі (такій як домашня або офісна мережа). Ці адреси не є доступними з Інтернету і використовуються для забезпечення комунікації між пристроями в межах локальної мережі.
Можна листуватися індивідуально:

Тоді отримувач побачить повідомлення у себе:

Або можна надіслати повідомлення одразу усім учасникам чата.

Передавання фотографії

### Деталі імплементації
- **Контроль затримки поширення:** Додаток активно відстежував затримку поширення ($\delta_i$) від кожного клієнта та пропускну здатність їх каналу ($B_i$). Ці показники були візуалізовані на схемі мережі.
- **Візуалізація:**
```javascript=
function updateGraph() {
console.log("Updating graph");
const idWithSameIp = new Map();
for (let sock of socketsId.keys()) {
let ip = sock.handshake.headers['x-forwarded-for'];
console.log(`IP of user ${sock.id}: ${ip}`);
if (!idWithSameIp.has(ip)) {
idWithSameIp.set(ip, []);
}
idWithSameIp.get(ip).push(sock.id);
}
io.emit("update_graph", Array.from(socketsId.values()), Array.from(idDelays), Array.from(idBandwidths), Array.from(idWithSameIp));
}
```
- **Масштабування ребер:** Товщина комунікаційних зв'язків (що представляють канали) була обчислена за допомогою формули:
$$ edges.scaling_i = \ln(B_{i}+\sqrt{B_{i}^2+1})= \text{arsinh}(B_{i}) $$
```javascript
function arcsinh(x) {
return Math.log(x + Math.sqrt(x * x + 1));
}
```
- **Масштабування вузлів:** Розмір комунікаційних вузлів (що представляють клієнтів) був обчислений за допомогою формули:
$$ node.scaling_i = \frac {200}{10+\delta_i/5} $$
```javascript
function node_scale(d) {
200 / (10 + d / 5);
}
```
- **Розрізнення клієнтів за IP-адресами:** Клієнти з різними IP-адресами були представлені вузлами різних кольорів, тоді як клієнти з однаковими IP-адресами отримували однаковий колір вузла.
### Бібліотеки, що використовувалися
У проекті використовувалися наступні бібліотеки Node.js:
- **express (^4.19.2):** Express - це швидкий, безпередворний, мінімалістичний веб-фреймворк для Node.js. Він надає надійний набір функцій для веб- та мобільних додатків.
- **socket.io (^4.7.5):** Socket.IO дозволяє реальний двосторонній обмін подіями між веб-клієнтами та серверами. Він спрощує розробку інтерактивних веб-додатків, які вимагають оновлень в реальному часі або функціональності обміну повідомленнями.
## Підсумки
Розробка багатоклієнтського серверного додатка з візуалізацією мережі виявилася успішною і ефективно відповідала вимогам проекту. Інтеграція API Socket.IO сприяла миттєвій комунікації та передачі даних між клієнтами, покращуючи загальну функціональність та користувацький досвід додатка. Крім того, візуалізація топології мережі та станів з'єднань надавала цінних уявлень про продуктивність мережі та сприяла кращому управлінню та усуненню неполадок.