Public Text Chat Server

image
Дана стаття буде цікава людям, які цікавляться мережами, логічним пристроєм серверів і нативним програмуванням. Тут не буде довгих лістингів вихідних кодів, а лише загальні начерки і підходи.
TL;DR GitHub

Це як имиджборж тільки текстовий
Такий же текст, як і по більшій мірі цей пост.
Повертаючись до своєї дитячої мрії, мені захотілося зробити текстовий чат. Для мене це як один з варіантів збільшити кількість відсутніх api в бібліотеці, оскільки тільки таким шляхом розумієш по-справжньому, що необхідно програмісту, коли пишеш щось більш менш прикладне.



Постановка проблеми

  • Реалізувати TCP-multithread текстовий чат-сервер, до якого можна коннектіться і отримувати розсилку повідомлень, а так само відправляти свої. В якості клієнта повинно бути неймовірно просте ПО – наприклад, nc. Або будь TCP-сокет, який приймає і відправляє дані (keep-alive, як звикли web-програмісти,.т.е підтримує з'єднання).
  • Сегментація трафіку за коштами стандартних чатрумов (міняємо чатрум більше не отримуємо дані користувачів в старому чатруме).
  • Т. к. є чатрумы – можливість перегляду людей в чатруме.
  • Прив'язка ніка до певної парі ip:port, при цьому можливість його змінювати.
  • Ну і така ж маленька текстова адмінка (викл сервера, отримання статті та подібне)


Теоритична частина

сокетах берклі, які працюють з протоколом TCP є API connect/accept, щоб виконати тристороння рукостискання, і потім в прихованому від програміста режимі організувати потік, з контролем доставки і цілісності даних. Проблема в тому, що conntect/accept це блокуючий виклик, і не можна підключиться до кількох портів одночасно (одним сокетом), щоб цього не робити і знизити навантаження на обчислювальний пристрій (підтримка великої кількості коннектов) придумали клієнт-серверну архітектуру, в якій сервер буде агрегувати весь трафік присылаемый на нього різними клієнтами і підтримувати ті самі множинні з'єднання.
Є два рішення проблеми підтримки множинних connect/accept для серверів – це мультипоточность і використання неблокирующих сокетів. Я буду розглядати перший випадок, тому що це мені ближче.

Проектування



Програмісти, що пишуть багатопотокові програми давно зіткнулися з безліччю проблем контролю доступу до ресурсів. Для цього використовуються м'ютекси, семафори, і т. д., про яких можна прочитати в википедии, або моєї статті опублікованій раніше і ще купі інших.

Тут вирішення проблеми доступу до ресурсів повністю покладено на плечі використовуваної бібліотеки, залишається тільки прописати логіку обробки отриманих даних.

Як я робив це
Для того, щоб написати TCPConnectionHandler, спочатку необхідно написати ThreadPool, який би мав можливість створення і переривання потоків (поділ потоків на тих, які перебувають у стані завершення, і тих, які знаходяться в роботі).
А TCPConnectionHandler дивився б якісь із з'єднань завершилися, відповідав за broadcast/multicast розсилки до підключеним сокетам, і зберігання/знищення даних, якими володіє сокет.

Структура даних сокета досить проста – це нік і чатрум, в якому знаходиться цей користувач. Звідси випливає простота використання такого механізму, щоб створити кімнату, потрібно просто перейти в неї.

Мікро-Адмінка

Адміністрування серверів, які підтримують тільки відкритий коннект (без шифрування) взагалі повинно заслуговувати окремої статті про те, як можна побудувати стійку систему одноразових паролів і хеш-комманд, але опустимо це все. Я просто використав можливість введення текстового ключа, і команди за ним, для виконання (Якщо довжина ключа буде досить велика декілька мегабайт, то можна убезпечити себе від брутфорса) але важко убезпечити себе від перехоплення цього самого ключа=). Але, теоретично, схема виглядає так:

  1. Сервер генерує число challenge або набір байт.
  2. Клієнт хеширует одноразовим ключем challenge + комманду і отруює хеш і комманду у відкритому вигляді.
  3. Сервер повторно хеширует команду з challenge і порівнює результат хеш з отриманим.
  4. Якщо хеш валідний то команда виконується.


Приклади команд

Вікно вітання з маленьким help.


Приховані можливості текстового чату

1. Обмін даними по хеш-чатрумам
Наприклад не один нормальний користувач не буде сидіти в чатруме з назвою PbgkkCzrM8VToEgcDcCSfQdw5p1IaoRHibu5d21xgv92c0fkmjuo3xoxfqtdn5tozmry5prsqti6ukfoztatqq==
А ось боти цілком. І змінювати ці кімнати через деякий час.

2. Прозоре шифрування в текстовому поданні Base64.
Ми всі вже звикли до автоматичного шифрування даних, а як буде ностальгічно слати дані співрозмовникам, які були зашифровані з pre-shared-key.

3. Анонімність, прив'язана тільки до пари ip:port (привіт tor, i2p), і ідентифікація/аутентифікація з співрозмовниками в межах підтримуваної сесії.


4. Легковажність даних.
Ніякого додаткового payload для підтримки сесії, або передачі контенту. Тільки текстовий контент.

5. Простий клієнт (nc, putty, etc)


6. Легковагість і продуктивність сервера
На моєму mac використовується бібліотека і клієнт скомпільовані без оптимізацій важать 156 + 40 = 196 Кб. Тобто можливість запускати на старих пристроях, з малою кількістю оперативної пам'яті, і мінімальною підтримкою POSIX.

7. OpenSource – відкритість, і нічого зайвого. + можливість внести свої власні доробки, як шифрування, ідентифікацію,
аутентифікацію, передачу файлів і т. д.


GitHub, але тримайте сильно-вразливих подалі від монітора.
CMake, дозволяє зібрати під свою платформу і запустити на локальному хості, mac/linux (+ windows in future з вашою допомогою).
Допиливание фіч на вимогу.


Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.