Учебный консольный групповой чат для локальной сети на WebSocket. Один сервер хранит пользователей и сообщения в SQLite и рассылает их; клиенты (по одному на пользователя) подключаются по WebSocket, общаются в общем канале и лично.
Проект разбит на 7 этапов. Каждая папка stepN/ — это самостоятельный рабочий проект
на конец соответствующего этапа (со своим go.mod, папками server/ и client/ и общим
пакетом protocol/). Каждый следующий этап = предыдущий + новый функционал.
| Компонент | Технология |
|---|---|
| Язык | Go 1.21+ |
| HTTP-сервер | github.com/gin-gonic/gin (маршруты и запуск, GET /ws) |
| WebSocket | github.com/gorilla/websocket (апгрейд соединения на /ws) |
| База данных | modernc.org/sqlite (чистый Go, без Си-компилятора) |
| Формат обмена | JSON (см. пакет protocol) |
| Этап | Папка | Что добавляет | Готово, когда |
|---|---|---|---|
| 1 | step1 — Каркас | Gin + GET /ws + апгрейд в WebSocket; SQLite с таблицами; клиент подключается |
сервер стартует, клиент подключается, есть chat.db с таблицами |
| 2 | step2 — Регистрация | клиент шлёт register; сервер выдаёт userID и сохраняет пользователя |
после ввода имени клиент получает userID, запись есть в users |
| 3 | step3 — Список онлайн и меню | реестр онлайн + рассылка user_list; меню у клиента |
два клиента видят друг друга; при отключении один пропадает у второго |
| 4 | step4 — Общий чат через HUB | HUB (одна горутина, каналы); group_msg сохраняется и рассылается всем |
три клиента в общем чате видят сообщения друг друга |
| 5 | step5 — Личные сообщения | private_msg → только адресату + эхо отправителю |
Аня пишет Боре — видит только Боря (у Васи нет) |
| 6 | step6 — История из SQLite | history_request → history из базы (общий/личный) |
при входе в чат видна прошлая переписка; переживает перезапуск |
| 7 | step7 — Экранный интерфейс | навигация по экранам, очистка экрана, «назад», непрочитанные | навигация как в ТЗ: выбор чата, очистка экрана, возврат «назад» |
В каждой папке одинаковый порядок. Пример для финальной версии:
# терминал 1 — сервер
cd step7
go run ./server # слушает :8080, создаёт chat.db
# терминал 2, 3, ... — клиенты
cd step7
go run ./client # к localhost:8080
go run ./client -addr 192.168.1.50:8080 # к серверу в локальной сети по его IPКлиент спросит имя и фамилию. В финальной версии: 0 — общий чат, номер — личный чат,
/back — назад в меню, q — выход. Подробности — в README внутри каждой папки.
Все сообщения — JSON с обязательным полем type. Структуры и константы — в stepN/protocol/protocol.go
(одинаковые на сервере и клиенте).
Клиент → сервер: register, group_msg, private_msg, history_request
Сервер → клиент: register_ok, user_list, group_msg, private_msg, history, error
- В gorilla нельзя писать в одно соединение из нескольких горутин — будет паника.
Поэтому у каждого клиента: одна горутина читает сокет, а исходящие складываются в личный
канал
send, из которого пишет одна горутина-писатель (writePump). - HUB (с этапа 4) — одна горутина, которая единолично владеет реестром клиентов (
map). Внешний мир общается с ним только через каналыregister/unregister/broadcast/directCh. Никакая другая горутина не трогает этотmapнапрямую — так мы избегаем гонок данных. - На этапе 3 (до HUB) реестр защищён мьютексом — это промежуточный, более простой вариант.
Файл chat.db создаётся сервером при старте. Таблицы:
users(id, first_name, last_name, online)messages(id, from_id, to_id, is_group, text, ts)—to_id = NULLиis_group = 1для общего канала.
- Go 1.21+ (проект проверялся на Go 1.26).
- Первая сборка скачивает зависимости и компилирует
modernc.org/sqlite— это может занять до минуты. - Порт по умолчанию
:8080. Если он занят другим приложением — освободите его или поменяйте порт вserver/main.go.