问题描述
我首先需要为我之前提出的问题道歉.(你可以查看我的个人资料)他们似乎提出的问题多于给出的答案.因此,我要列出引发所有荒谬问题的实际问题.
我正在尝试设计一个聊天小程序.到目前为止,我已经编写了小程序、servlet 以及小程序和 servlet 之间的通信.servlet 端的代码使我能够使用小程序在客户端之间建立聊天,但该代码更像是一个广播所有功能,即所有客户端都将相互聊天.这是我开始设计聊天小程序时的第一个目标.第二步是仅在两个特定用户之间聊天,就像我们拥有的任何其他聊天应用程序一样.所以这就是我的想法:
- 我创建了一个包含广播所有"代码的 servlet 实例.
- 然后我将这个实例的地址传递给相应的客户端.
- 2 个客户端小程序使用该地址进行聊天.从技术上讲,代码是全广播",但由于只有 2 个客户端连接到它,因此它提供了两个客户端之间的聊天功能.因此,2 个客户端的组具有相同 servlet 的不同实例,并且每个实例最多处理两个客户端之间的聊天.
然而,正如预测的那样,这个想法没有实现!
我尝试创建一个 servlet 实例,但唯一的解决方案是在 servlet 端使用会话,我不知道如何使用此会话进行以后的通信.>
我现在知道如何使用 request.getSession().所以我在它的 param 标签中为一个小程序设置了会话,并使用它来与 servlet 进行进一步的通信.但是我如何使用这些数据在两个客户端之间建立聊天呢?正如我之前写的,我有broadcast_all聊天的代码如下:
public class CustomerServlet extends HttpServlet {公共字符串 getNextMessage() {//创建一个消息接收器以等待来自//消息源.返回新的 MessageSink().getNextMessage(source);}@覆盖protected void doGet(HttpServletRequest 请求,HttpServletResponse 响应)抛出 ServletException,IOException {ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());String recMSG = getNextMessage();dout.writeObject(recMSG);dout.flush();}公共无效广播消息(字符串消息){//将消息发送给所有通过 HTTP 连接的客户端//消息到消息源source.sendMessage(消息);}@覆盖protected void doPost(HttpServletRequest 请求,HttpServletResponse 响应)抛出 ServletException,IOException {尝试 {ObjectInputStream din= new ObjectInputStream(request.getInputStream());String message = (String)din.readObject();ObjectOutputStream dout = new ObjectOutputStream(response.getOutputStream());dout.writeObject("1");dout.flush();如果(消息!= null){广播消息(消息);}//设置状态码表示没有响应response.setStatus(response.SC_NO_CONTENT);} 捕获(异常 e){e.printStackTrace();}}MessageSource source = new MessageSource();}类 MessageSource 扩展了 Observable {公共无效发送消息(字符串消息){设置更改();通知观察者(消息);}}类 MessageSink 实现观察者{字符串消息 = 空;//由 update() 设置并由 getNextMessage() 读取//消息源收到新消息时调用同步公共无效更新(Observable o,对象arg){//获取新消息消息=(字符串)arg;//唤醒我们的等待线程通知();}//获取消息源发出的下一条消息同步公共字符串 getNextMessage(MessageSource source) {//告诉源我们希望被告知新消息source.addObserver(this);//等到我们的 update() 方法收到消息而(消息==空){尝试 {等待();} 捕获(异常 e){System.out.println("发生异常!ERR ERR ERR");}}//告诉源停止告诉我们新消息source.deleteObserver(this);//现在返回我们收到的消息//但首先将消息实例变量设置为空//因此可以再次调用 update() 和 getNextMessage().字符串 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 将特定观察者分配给特定对象)?
我首先决定问个别问题,比如如何创建 servlet 的实例,在 stackoverflow 中使用 observable 和观察者的对象等等......但我更加困惑.谁能告诉我如何仅在两个客户端之间建立聊天?(我使用的是 Http 而不是套接字或 RMI).
问候,米顿.
P.S. 感谢所有回答我之前(荒谬的)问题的人.我应该早点说明目的,以便你们更好地帮助我.
您需要将所有连接的用户存储在 application 范围内的 Map
中使用 ServletContext#setAttribute()
.String
表示唯一的用户标识符(聊天昵称?).您还需要使用 HttpSession#setAttribute()
在 session 范围内存储特定的聊天 User
.您还需要将 other 用户存储在相关用户的 会话 范围内的 Map
中的单个聊天中.您可以通过 getAttribute()
方法获取该属性.
通过这种方式,您可以知道哪些用户全部可用,哪些用户在当前会话中以及与哪些用户单独聊天.
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.
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;
}
}
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.
You need to store all connected users in a Map<String, User>
in the application scope using ServletContext#setAttribute()
. The String
denotes the unique user identifier (chat nickname?). You need to store the specific chat User
as well in the session scope using HttpSession#setAttribute()
. You also need to store the other user in individual chats in a Map<String, User>
in the session scope of the users in question. You can obtain the attribute by the getAttribute()
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.
这篇关于如何使用小程序和 servlet 启动两个客户端和两个客户端之间的聊天?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!