#java #sockets #networking #chat
#java #сокеты #сеть #Чат
Вопрос:
Я разрабатываю приложение для общения в чате. У меня проблема. Как я могу обнаружить конкретного клиента поверх сервера?
Я использую классы ServerSocket
и Socket
для связи.
Комментарии:
1. На этот вопрос почти недостаточно информации для ответа. Ваш код должен отслеживать соединения и каким-то образом связывать их с клиентами. Все остальное зависит от вашего дизайна / кода.
Ответ №1:
Используйте getInetAddress()
of Socket
для получения адресов клиентов.
Socket clientSocket = server.accept();
InetAddress clientAddress = clientSocket.getInetAddress();
Если у вас есть клиенты, уникальные для данного ip-адреса, вы можете сделать clientAddress.getHostAddress()
, чтобы получить IP-адрес клиента.
Комментарии:
1. Если вы заходите из-за брандмауэра. например, у всех пользователей AOL может показаться, что у всех них один и тот же исходный IP-адрес.
Ответ №2:
Стандартный подход, когда клиент подключается к серверу, заключается в отправке имени пользователя и пароля для идентификации клиента. Если вы хотите, чтобы это было прозрачно, вы можете использовать System.getProperty("user.name")
, который прост, но не очень безопасен.
Комментарии:
1. Внутри компании имена пользователей будут уникальными. Если это интернет-приложение, пользователю придется ввести имя пользователя.
2. Спасибо за разъяснение. Я думал об «Интернете» и не учел, что все пользователи могут быть из одной организационной структуры.
Ответ №3:
Я просто приведу грубую суть и улучшу ее позже, но здесь идет:
Обзор:
Итак, вы сохраняете некоторые данные на сервере, а затем, когда клиент подключается, он отправляет имя пользователя и пароль и аутентифицируется на основе этих данных. Вы сохраняете конечную точку Socket
на карте, которая является String username -> Socket socket
. Также сохраните обратное, Socket socket -> String username
. Используйте это, чтобы найти имя пользователя, когда вы получаете что-то из сокета. Даже если вы используете каналы сокетов, вы все равно можете получить сокет из канала, используя методы канала.
Для управления этими соединениями с помощью NIO:
О чем я не говорил, так это о том, как вы будете получать данные имени пользователя / пароля в первую очередь. Для этого я советую создать фрейминг. Прочитайте размер данных, а затем прочитайте тип данных, который должен быть двумя целыми числами. Вы можете записывать объекты непосредственно в поток сокета и обрабатывать их в том же порядке на другом конце.
Вы должны использовать селектор с ключами выбора и сохранять полученные данные в буферах, прикрепленных к этим ключам выбора. Затем вы просто продолжаете выбирать и добавлять полученные данные в буфер, если сокет доступен для чтения, пытаясь обработать буфер. Если в буфере есть полезные данные после записи в него из чтения (т. Е. вы получили размер данных, а также полную длину данных), вам нужно удалить данные и сжать буфер — т. Е. переместить позицию буфера вверх на размер длины данных (размер int) размер типа данных (размер int) длина данных, а затем уменьшить весь набор до 0 и установить позицию в конец текущих полученных данных. Используйте buffer.compact()
для этого.
Я бы действительно посоветовал что-то вроде KryoNet для выполнения тяжелой работы. Сетевое программирование — сложная задача. Но это может быть для назначения, так что…