Skip to content
This repository was archived by the owner on Sep 9, 2021. It is now read-only.

Conversation

DeKinci
Copy link

@DeKinci DeKinci commented Jan 18, 2021

No description provided.

@DeKinci
Copy link
Author

DeKinci commented Jan 18, 2021

Сборка

Сборка осуществляется с помощью Maven и JDK (1.8+).
Для удобства в репозиторий помещён Maven Wrapper.
Эта утилита скачает необходимую версию Maven или использует существующую.
Таким образом в системе должен присутствовать только JDK

./mvnw package

После сборки в корне проекта появятся 4 .jar всадника с говорящими именами:
client.jar
server.jar
nioclient.jar
nioserver.jar

Запуск

Любого приложения:
java -jar <filename> <args>

Аргумент клиента: username@ip:port по умолчанию рандомная цифра@localhost:4269

Аргумент сервера: port по умолчанию 4269

Клиенты поддерживают ввод через pipe cat big.txt | java -jar client.jar, но соединение не закрывается (EOF игнорируется)

Протокол

Протокол универсальный, в основе пары ключ-значение.

Начало сообщения 02h Количество пар Длина ключа UTF-8 ключ Длина значения UTF-8 значение ...

Если длина ключа или значения превышает некоторый размер (захардкожено 400 байт), то применяется backpressure - после каждых 400 байт отправитель будет дожидаться подтверждения от клиента.
Это странное поведение, силами знакомых лиц объяснить причину не получилось. При слишком интенсивной передаче данных часть не доходила до получателя.

Статусные сообщения:
Подтверждение 01h
Сообщение 02h
Пинг (не обрабатывается) 03h

Формат сообщений
Для чата протокол используется в формате
__type: тип сообщения
поле: значение

Handshake - приветственное сообщение от клиента
name: Client name

Используемые форматы сообщений:
Announcement - сообщение от сервера
ts: Timestamp
text: Text

Kick - сообщение об отключении сервером (совпадение ников)
ts: Timestamp
text: Text

MessageUpdate - ретрансляция сообщения другого клиента от сервера
name: Client name
ts: Timestamp
text: Text

Message - отправка сообщения с клиента на сервер
text: Text

Реализация

Заняла намного больше ожидаемого времени (неблокирующие сокеты, внезапно, неудобно писать), и на данный момент коду не помешает прическа.
И клиент и сервер регулярно (каждые 500мс) посылают друг другу ping для отслеживания обрыва канала - в отдельном потоке.
При оправке сообщения 'long' клиент сгенерирует и отправит 10МБ текста

Клиент
В фоновом потоке происходит чтение сокета и обработка полученных сообщений.
В основном потоке происходит считывание System.in и отправка сообщений.

Сервер
На каждое новое подключение создается отдельный поток для его обработки.
Массовые рассылки происходят в отдельном потоке через очередь.

Неблокирующий клиент
В фоновом потоке происходит считывание с клавиатуры и добавление в буфер отправки.
В основном потоке происходит постоянная отправка и получение доступных данных, а также их обработка

Неблокирующий сервер
В единственном потоке происходит постоянное считывание и обработка доступных данных.

@wrbbz
Copy link
Contributor

wrbbz commented Jan 18, 2021

UPD:

Блокирующие:

  • Невозможность наконфижить ip в случае сервера
  • Спаминг сообщениями в случае ошибки (например, дублирующийся ник или невозможность подключения)

В остальном, вроде как, все ок

Неблокирующие:

  • Не работает маппинг сервера на какой-то IP/порт. Сервер, вроде как, запускается. Но Connection refused
  • Кик при дублирующем нике не работает. Клиент висит. Сервер выплевывает исключение:

Client:

➜ java -jar nioclient.jar kekess@localhost:4269
Connecting to kekess@localhost:4269

Server:

➜ java -jar nioserver.jar
Running server on port 4269
127.0.0.1:57832 aka kekess connected
127.0.0.1:57832 aka kekess incoming message of length 4
127.0.0.1:57834 aka kekess kicked for duplicating name
Exception in thread "main" java.nio.channels.CancelledKeyException
	at java.base/sun.nio.ch.SelectionKeyImpl.ensureValid(SelectionKeyImpl.java:74)
	at java.base/sun.nio.ch.SelectionKeyImpl.readyOps(SelectionKeyImpl.java:133)
	at java.base/java.nio.channels.SelectionKey.isWritable(SelectionKey.java:378)
	at com.dekinci.uni.net.first.nio.NonBlockingServer.handleConnections(NonBlockingServer.kt:58)
	at com.dekinci.uni.net.first.nio.NioServerMainKt.main(NioServerMain.kt:12)

Ну и сервер перестает отвечать клиентам

В целом, по коду все ок

@DeKinci
Copy link
Author

DeKinci commented Jan 18, 2021

Сервера теперь конфижутся ip:host, по умолчанию localhost:4269
Пофикшены сообщение при отключении

@wrbbz
Copy link
Contributor

wrbbz commented Jan 18, 2021

Что теперь:

  • Маппинг работает в блокирующих, но при отключении сервера, порт остается занят
  • Маппинг не работает в неблокирующих
  • Отключение сервера при работающих клиентах ведет к спамингу сообщениями на клиенте ConnectException Connection refused

@DeKinci
Copy link
Author

DeKinci commented Jan 18, 2021

Последнее фича - реконнект, остальные пошел чинить

@DeKinci
Copy link
Author

DeKinci commented Feb 23, 2021

Исправлена занятость порта (временная) выставлением флага SO_REUSEADDR
Исправлены мапиинги в неблокирующем сервере использованием аргументов

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants