- Java - из-за учебы было пару дней на написание программ, поэтому пошел по легкому пути и решил писать на java. Так же благодаря этому программы получились кросс-платформенными. (при наличии большего времени использовал бы C++, тесты, к сожалению, не успел написать по той же причине)
- Так как сокеты используют TCP, то не пришлось заботиться о подтверждении получения сообщений и программы полагаются на то, что если метод отправки сообщений не выкинул исключение, то сообщение считается доставленным.
- Соединения не защищены, так как для этого нужен доверенный сертификат (который помешал бы запуску в локальной сети), а с добавлением само-подписного сертификата в клиент не успел разобраться. А так как соединения не защищены, то не видел смысла шифровать пароли на сервере.
- Так как пользователей может быть много, то для каждого нового сокета заводится отдельный поток-демон и ждать приходится только при обращении к общим полям сервера.
- По-хорошему для мессенджера надо использовать noSQL базу данных, но если я правильно понял, то задание рассчитано не на это и я использовал HashMap для хранения данных о пользователях.
- API рассчитан на асинхронное получение и отправку сообщений, чтобы не возникало проблем с получением любых данных в любой момент и можно было остановить потоки-демоны слушающие сокеты при остановке основного потока сервера без дополнительной обработки получения ошибок при ожидании ответа. (синхронные ответы ожидаются только при аутентификации)
- Для графического интерфейса клиента используется Swing, так как он уже есть в составе jdk и довольно прост в использовании.
- Для запуска достаточно запустить скрипт
jar.sh, который создастclient.jarиserver.jar, которые можно запустить командойjava -jar *. - jar-файлы уже созданы на случай наличия только JRE.
clientожидает запуск в форматеclient [defaultHost [defaultPort]].serverожидает запуск в форматеserver [port], по-умолчанию порт будет 31337.
Для корректной остановки сервера нужно ввестиstop.
- Кодировка - UTF8
- В конце каждого сообщения должен идти символ перевода строки
auth <login> <password>- попытка авторизации
reg <login> <password>- попытка регистрации
В ответ на данные запросы придетAcceptedв случае успеха или сообщение с описанием ошибки в противном случае. ПослеAcceptedожидается сообщение в форматеFriendsList <n>( <username> <id> <unreadMessages>){n}.GetFriendsRequestsList- извещает сервер о том, что мы хотим получить список запросов в друзья.AcceptRequest <id>- сообщает серверу, что мы принимаем запрос от данного пользователя.SendRequest <username>- посылает запрос заданному пользователю, если такой существует.SendMessage <id> <message>- посылает сообщение заданному пользователю, если он уже есть в списке друзей.GetMessageFrom <id>- извещает сервер о том, что мы хотим получить самое первое новое сообщение от заданного пользователя.
Notification <message>- информационное сообщение.NewFriend <username> <id>- сообщает, что в списке друзей пользователя появился новый пользователь.NumberOfRequests <n>- сообщает количество запросов в друзья.RequestsList <n>( <username> <id>){n}- список всех запросов в друзья.UnreadMessages <id> <n>- сообщает количество новых сообщений от пользователя.NewMessage <id> <message>- отправляет первое новое сообщение от пользователя.
Использованные условные обозначения:
<username> - имя пользователя, не должно содержать пробельных символов.
<password> - пароль пользователя, не должен содержать символов перевода строки.
<id> - id пользователя.
<n> - число.
<id>, <n> - целые, не отрицательные, беззнаковые числа.
<message> - сообщение, не должно содержать символов перевода строки.
<unreadMessages> - количество новых сообщений от пользователя.
(...){n} - n повторений сообщения внутри круглых скобок.