如何使用 applet 和 servlet 在两个客户端和仅两个客户端之间发起聊天?
我首先需要为我之前的问题道歉。 (你可以查看我的个人资料)他们似乎提出的问题多于给出的答案。因此,我提出了引发所有这些荒谬问题的实际问题。
我正在尝试设计一个聊天小程序。到目前为止,我已经编写了applet、servlet 以及applet 和servlet 之间的通信。 servlet 端的代码使得我能够使用小程序在客户端之间建立聊天,但该代码更像是广播所有功能,即所有客户端都将相互聊天。这是我开始设计聊天小程序时的第一个目标。第二步是仅在两个特定用户之间聊天,就像我们拥有的任何其他聊天应用程序一样。这就是我的想法:
- 我创建一个具有“broadcast-all”代码的 servlet 实例。
- 然后,我将此实例的地址传递给相应的客户端。
- 2 个客户端小程序使用该地址进行聊天。从技术上讲,该代码是“全部广播”,但由于只有 2 个客户端连接到它,因此它提供了两个客户端之间的聊天功能。因此,2 个客户端组成的组具有同一 servlet 的不同实例,并且每个实例最多处理两个客户端之间的聊天。
然而,正如预料的那样,这个想法并没有实现!
我尝试创建 servlet 的实例,但唯一的解决方案是在 servlet 端使用会话,而且我不知道如何使用此会话进行以后的通信。
我现在知道如何使用 request.getSession()。因此,我在小程序的 param 标记中设置了会话,并使用它与 servlet 进行进一步的通信。但是我如何使用这些数据在两个客户端之间建立聊天?正如我之前所写,我的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 方法连接到上面的 servlet 以获取新消息。它使用 while 循环,并阻塞直到从 servlet 收到消息。每当客户端输入消息时,主线程都会使用 POST 方法与 servlet 进行通信。目前所有客户都在与大家聊天。我想使用上面使用的相同方法(或者如果可能的话任何其他方式)来建立两个客户端之间和仅两个客户端之间的聊天。我可能会在小程序中设置另一个线程来检查是否有任何其他用户希望与其聊天,然后交换一些数据,以便只有这两个用户聊天...
然后我尝试修改我的广播所有代码。在该代码中,我使用了实现 Observer 和 Observable 接口的类。所以我得到的下一个想法是:
- 创建一个 Observable 类的新对象(比如 class_1)。该对象为 2 个客户端所共有。
- 想要聊天的 2 个客户端将使用 class_1 的相同对象。
- 其他 2 个客户端将使用 class_1 的不同对象。
但这里的问题在于实现 Observer 接口的类(比如 class_2)。由于观察者监视同一类型的类,即 class_1,我如何建立一个观察者监视 class_1 的一个对象,另一个观察者监视同一类 class_1 的另一个对象(因为 notifyObservers() 会通知所有观察者,我可以' t 将特定观察者分配给特定对象)?
我首先决定问一些个人问题,比如如何在 stackoverflow 中创建 servlet 的实例、使用 observable 和observer 的对象等等……但我更加困惑了。谁能给我一个想法如何仅在两个客户端之间建立聊天?(我使用的是 Http 而不是套接字或 RMI)。
问候, 米图恩.
PS感谢所有回复我之前(荒谬)问题的人。我应该早点说出目的,这样你们才能更好地帮助我。
I first need to apologize for my earlier questions. (You can check my profile for them)They seemed to ask more questions than give answers. Hence, I am laying down the actual question that started all them absurd questions.
I am trying to design a chat applet. Till now, I have coded the applet, servlet and communication between the applet and the servlet. The code in the servlet side is such that I was able to establish chatting between clients using the applets, but the code was more like a broadcast all feature, i.e. all clients would be chatting with each other. That was my first objective when I started designing the chat applet. The second step is chatting between only two specific users, much like any other chat application we have. So this was my idea for it:
- I create an instance of the servlet that has the 'broadcast-all' code.
- I then pass the address of this instance to the respective clients.
- 2 client applets use the address to then chat. Technically the code is 'broadcast-all', but since only 2 clients are connected to it, it gives the chatting between two clients feature. Thus, groups of 2 clients have different instances of the same servlet, and each instance handles chatting between two clients at a max.
However, as predicted, the idea didn't materialize!
I tried to create an instance of the servlet but the only solution for that was using sessions on the servlet side, and I don't know how to use this session for later communications.
I now know how to use the request.getSession(). So I set the session for an applet in its param tag and use it for further communications with the servlet. But how do I use this data to establish chatting between two clients? As I wrote earlier, I have the code for broadcast_all chatting as follows:
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;
}
}
On the applet side, I have a thread that will connect to the servlet above using GET method to get new messages. It uses a while loop, and blocks until it gets a message from the servlet. The main thread communicates with the servlet using POST method whenever the client has entered the message. Currently all clients chat with everyone. I want to use the same methods used above (or if possible any other way) to establish chatting between two clients and two clients only. I could possibly have another thread in the applet to check if any other user wishes to chat with it and then exchange some data so that only those two user chat...
I then tried to modify my broadcast-all code. In that code, I was using classes that implemented Observer and Observable interfaces. So the next idea that I got was:
- Create a new object of the Observable class(say class_1). This object be common to 2 clients.
- 2 clients that wish to chat will use same object of the class_1.
- 2 other clients will use a different object of class_1.
But the problem here lies with the class that implements the Observer interface(say class_2). Since this has observers monitoring the same type of class, namely class_1, how do I establish an observer monitoring one object of class_1 and another observer monitoring another object of the same class class_1 (Because notifyObservers() would notify all the observers and I can't assign a particular observer to a particular object)?
I first decided to ask individual problems, like how to create instances of servlets, using objects of observable and observer and so on in stackoverflow... but I got confused even more. Can anyone give me an idea how to establish chatting between two clients only?(I am using Http and not sockets or RMI).
Regards,
Mithun.
P.S. Thanks to all who replied to my previous (absurd) queries. I should have stated the purpose earlier so that you guys could help me better.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您需要使用
ServletContext#setAttribute()
将所有连接的用户存储在 application 范围内的Map
中。String
表示唯一的用户标识符(聊天昵称?)。您还需要使用HttpSession#setAttribute()
将特定聊天User
存储在 session 范围内。您还需要将各个聊天中的其他用户存储在相关用户的会话范围内的Map
中。您可以通过getAttribute()
方法获取属性。这样您就可以知道哪些用户全部可用、哪些用户在当前会话中以及正在与哪些用户单独聊天。
You need to store all connected users in a
Map<String, User>
in the application scope usingServletContext#setAttribute()
. TheString
denotes the unique user identifier (chat nickname?). You need to store the specific chatUser
as well in the session scope usingHttpSession#setAttribute()
. You also need to store the other user in individual chats in aMap<String, User>
in the session scope of the users in question. You can obtain the attribute by thegetAttribute()
method.This way you know which users are all available and which user is in the current session and with which users it is individually chatting.
这是一种粗略的方法,但我就是找不到可行的解决方案。我所做的是让所有用户连接到具有broadcastAll 代码的servlet。 每个用户都会知道他正在与哪个其他用户聊天。因此,在发送消息时,用户会将他的姓名以及正在与他聊天的用户的姓名附加到消息中。由于它是广播所有代码,因此每个连接的用户都会收到该消息。用户收到消息后,解析该消息以获取发送该消息的用户以及该消息的目标用户的名称。它将这两个名称与其记录进行比较 - 请参阅前面粗体的声明。如果匹配,它将显示该消息,否则忽略它。
再说一遍,这是一种粗略的方法,我相信有更好的解决方案。
This is a crude way to do it, but I just couldn't find a feasible solution. What I did was that I made all users connect to the servlet that had the broadcastAll code. Each user would be aware of which other user it is chatting with. Hence, while sending a message, the user would append his name and the name of the user that he is chatting with to the message. Since it is a broadcastAll code, every connected user would receive the message. After receiving the message, the user would parse the message to get the user who sent the message, and the name of the user for whom the message was intended. It would compare these two names with its records - see the statement in bold earlier. If matched it would display the message, else ignore it.
Again, its a crude way to do it and I am sure there are better solution out there.