Как инициировать общение между двумя клиентами и двумя клиентами только с помощью апплетов и сервлетов?
Мне сначала нужно извиниться за мои предыдущие вопросы. (Вы можете проверить мой профиль для них) Они, казалось, задавали больше вопросов, чем дают ответы. Следовательно, я задаю фактический вопрос, который вызвал все эти абсурдные вопросы.
Я пытаюсь создать чат-апплет. До сих пор я закодировал апплет, сервлет и связь между апплетом и сервлетом. Код на стороне сервлета таков, что я смог установить чат между клиентами с помощью апплетов, но код был больше похож на широковещательную функцию, т.е. Все клиенты будут общаться друг с другом. Это была моя первая цель, когда я начал разрабатывать чат-апплет. Второй шаг - общение между двумя конкретными пользователями, как и любое другое приложение для чата. Итак, это была моя идея:
- Я создаю экземпляр сервлета, который имеет код "широковещательный все".
- Затем я передаю адрес этого экземпляра соответствующим клиентам.
- 2 апплета клиента используют адрес для чата. Технически код "broadcast-all", но поскольку к нему подключено только 2 клиента, он дает возможность общаться между двумя клиентами. Таким образом, группы из двух клиентов имеют разные экземпляры одного и того же сервлета, и каждый экземпляр обрабатывает чаты между двумя клиентами с максимальным значением.
Однако, как и было предсказано, идея не оправдалась!
Я попытался создать экземпляр сервлета, но единственным решением для этого было использование сеансов на стороне сервлета, и я не знаю, как использовать этот сеанс для более поздних сообщений.
Теперь я знаю, как использовать request.getSession(). Поэтому я установил сеанс для апплета в свой тег param и использовал его для дальнейшей связи с сервлетом. Но как я могу использовать эти данные для установления чата между двумя клиентами? Как я писал ранее, у меня есть код для широковещательной беседы broadcast_all:
public class CustomerServlet extends HttpServlet {
public String getNextMessage() {
// Create a message sink to wait for a new message from the
// message source.
return new MessageSink().getNextMessage(source);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());
String recMSG = getNextMessage();
dout.writeObject(recMSG);
dout.flush();
}
public void broadcastMessage(String message) {
// Send the message to all the HTTP-connected clients by giving the
// message to the message source
source.sendMessage(message);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try {
ObjectInputStream din= new ObjectInputStream(request.getInputStream());
String message = (String)din.readObject();
ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());
dout.writeObject("1");
dout.flush();
if (message != null) {
broadcastMessage(message);
}
// Set the status code to indicate there will be no response
response.setStatus(response.SC_NO_CONTENT);
} catch (Exception e) {
e.printStackTrace();
}
}
MessageSource source = new MessageSource();
}
class MessageSource extends Observable {
public void sendMessage(String message) {
setChanged();
notifyObservers(message);
}
}
class MessageSink implements Observer {
String message = null; // set by update() and read by getNextMessage()
// Called by the message source when it gets a new message
synchronized public void update(Observable o, Object arg) {
// Get the new message
message = (String)arg;
// Wake up our waiting thread
notify();
}
// Gets the next message sent out from the message source
synchronized public String getNextMessage(MessageSource source) {
// Tell source we want to be told about new messages
source.addObserver(this);
// Wait until our update() method receives a message
while (message == null) {
try {
wait();
} catch (Exception e) {
System.out.println("Exception has occured! ERR ERR ERR");
}
}
// Tell source to stop telling us about new messages
source.deleteObserver(this);
// Now return the message we received
// But first set the message instance variable to null
// so update() and getNextMessage() can be called again.
String messageCopy = message;
message = null;
return messageCopy;
}
}
На стороне апплета у меня есть поток, который будет подключаться к сервлету выше, используя метод GET для получения новых сообщений. Он использует цикл while и блокирует, пока не получит сообщение от сервлета. Основной поток связывается с сервлетом с использованием метода POST всякий раз, когда клиент ввел сообщение. В настоящее время все клиенты беседуют со всеми. Я хочу использовать те же методы, которые использовались выше (или, если возможно, любым другим способом), чтобы установить чат между двумя клиентами и двумя клиентами. Я мог бы иметь еще один поток в апплете, чтобы проверить, хочет ли какой-либо другой пользователь общаться с ним, а затем обмениваться некоторыми данными, чтобы только те два пользовательских чата...
Затем я попытался изменить свой код для вещания. В этом коде я использовал классы, которые реализовали интерфейсы Observer и Observable. Итак, следующая идея, которую я получил, заключалась в следующем:
- Создайте новый объект класса Observable (скажем, class_1). Этот объект является общим для 2 клиентов.
- 2 клиента, которые хотят общаться, будут использовать один и тот же объект класса_1.
- 2 других клиента будут использовать другой объект класса_1.
Но проблема здесь заключается в классе, реализующем интерфейс Observer (скажем, class_2). Поскольку наблюдатели наблюдают за тем же типом класса, а именно с классом_1, как установить наблюдателя, который контролирует один объект класса_1, а другой наблюдатель контролирует другой объект того же класса class_1 (поскольку notifyObservers() уведомит всех наблюдателей, и я могу " t назначить конкретный наблюдатель конкретному объекту)?
Сначала я решил задать индивидуальные проблемы, например, как создавать экземпляры сервлетов, использовать объекты наблюдаемого и наблюдателя и т.д. в stackoverflow... но я еще больше запутался. Может ли кто-нибудь дать мне представление о том, как установить чат между двумя клиентами? (Я использую Http, а не сокеты или RMI).
С уважением,
Митхун.
P.S. Спасибо всем, кто ответил на мои предыдущие (абсурдные) запросы. Я должен был сказать цель раньше, чтобы вы, ребята, могли мне помочь.
Ответы
Ответ 1
Вам нужно сохранить всех подключенных пользователей в Map<String, User>
в области приложения, используя ServletContext#setAttribute()
. String
обозначает уникальный идентификатор пользователя (chat nickname?). Вы должны сохранить конкретный чат User
, а также в области сеанса, используя HttpSession#setAttribute()
. Вам также необходимо сохранить другого пользователя в отдельных чатах в Map<String, User>
в области сеанса для пользователей, о которых идет речь. Вы можете получить атрибут с помощью метода getAttribute()
.
Таким образом, вы знаете, какие пользователи доступны и какой пользователь находится в текущем сеансе и с которыми пользователи в отдельности беседуют.
Ответ 2
Это грубый способ сделать это, но я просто не мог найти приемлемого решения. Что я сделал, так это то, что я подключил всех пользователей к сервлету с кодом broadcastAll. Каждый пользователь будет знать, с каким другим пользователем он общается. Следовательно, при отправке сообщения пользователь будет добавлять свое имя и имя пользователя, с которым он беседует с этим сообщением. Поскольку это код broadcastAll, каждый подключенный пользователь получит сообщение. После получения сообщения пользователь будет анализировать сообщение, чтобы получить пользователя, который отправил сообщение, и имя пользователя, для которого предназначалось сообщение. Он сравнивал бы эти два имени со своими записями - см. Выражение, выделенное полужирным шрифтом. Если оно соответствует, оно отобразит сообщение, иначе игнорируйте его.
Опять же, это грубый способ сделать это, и я уверен, что там есть лучшее решение.