【问题标题】:How to initiate chatting between two clients and two clients only, using applets and servlets?如何使用 applet 和 servlet 在两个客户端和两个客户端之间发起聊天?
【发布时间】:2011-02-03 18:33:51
【问题描述】:

我首先需要为我之前的问题道歉。 (你可以查看我的个人资料)他们似乎提出的问题多于给出的答案。因此,我提出了引发所有这些荒谬问题的实际问题。

我正在尝试设计一个聊天小程序。到目前为止,我已经编写了applet、servlet以及applet和servlet之间的通信。 servlet 端的代码使我能够使用小程序在客户端之间建立聊天,但代码更像是广播所有功能,即所有客户端都将相互聊天。这是我开始设计聊天小程序时的第一个目标。第二步是只在两个特定用户之间聊天,就像我们拥有的任何其他聊天应用程序一样。所以这是我的想法:

  1. 我创建了一个具有“全部广播”代码的 servlet 实例。
  2. 然后我将此实例的地址传递给相应的客户端。
  3. 2 个客户端小程序使用该地址进行聊天。从技术上讲,该代码是“全部广播”,但由于只有 2 个客户端连接到它,它提供了两个客户端之间的聊天功能。因此,2 个客户端的组具有相同 servlet 的不同实例,每个实例最多处理两个客户端之间的聊天。

但是,正如预期的那样,这个想法没有实现!

我尝试创建 servlet 的实例,但唯一的解决方案是在 servlet 端使用会话,我不知道如何使用此会话进行以后的通信。 p>

我现在知道如何使用 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 接口的类。所以我得到的下一个想法是:

  1. 创建 Observable 类的新对象(比如 class_1)。此对象对 2 个客户端是通用的。
  2. 2 个希望聊天的客户将使用 class_1 的相同对象。
  3. 其他 2 个客户端将使用 class_1 的不同对象。

但这里的问题在于实现 Observer 接口的类(比如 class_2)。由于这有观察者监视相同类型的类,即 class_1,我如何建立一个观察者监视 class_1 的一个对象,另一个观察者监视同一类 class_1 的另一个对象(因为 notifyObservers() 会通知所有观察者,我可以' t 将特定观察者分配给特定对象)?

我首先决定提出个别问题,例如如何创建 servlet 的实例,在 stackoverflow 中使用 observable 和 observer 的对象等等......但我更加困惑。谁能告诉我如何仅在两个客户端之间建立聊天?(我使用的是 Http 而不是套接字或 RMI)。

问候, 米通。

P.S.感谢所有回复我之前(荒谬)问题的人。我应该早点说明目的,以便你们更好地帮助我。

【问题讨论】:

  • 您在发布此问题之前是否阅读了我的回答? stackoverflow.com/questions/2566496/…您最好编辑原始问题以包含更多细节。这两个问题归结为相同。
  • 是的,我刚刚做到了。它清楚地回答了会话部分。谢谢。但是我仍然不明白如何仅在两个客户端之间建立聊天。此外,我将编辑以上内容以包含更多细节。

标签: java http servlets applet chat


【解决方案1】:

您需要使用ServletContext#setAttribute() 将所有连接的用户存储在应用程序 范围内的Map<String, User> 中。 String 表示唯一的用户标识符(聊天昵称?)。您还需要使用HttpSession#setAttribute() 将特定聊天User 存储在会话 范围内。您还需要将 other 用户存储在相关用户的 session 范围内的 Map<String, User> 中的个人聊天中。可以通过getAttribute()方法获取属性。

这样您就知道哪些用户都可用,哪些用户在当前会话中,以及正在与哪些用户单独聊天。

【讨论】:

  • 在地图中,“string”是一个客户的名字(昵称)。什么是“用户”?是“字符串”正在与之聊天的用户名吗?
  • 它应该是一个代表相关客户/用户的值对象。它可以包含有关用户名、ip、与之聊天的其他用户、历史记录等的信息,无论你喜欢什么。你当然也可以只使用用户名的List<String>
  • 好的。到目前为止,我已经理解了这一点: 1. 在 applet 方面,我做了你在另一个“servlet 实例”问题中要求我做的更改 2. 在 servlet 方面,我记下了所有连接的用户。我将使用 LIST 而不是 MAP,并将唯一用户添加到应用程序上下文中的列表中。在那之后,我只是失去了你。尽管如此,你已经给了我一个想法 w.r.t 设置会话.. 我会努力的。谢谢
  • 在应用程序的生命周期中只有一个 servlet 实例。利用应用程序范围了解哪些用户都可用。利用用户当前正在请求 servlet 以及当前正在与哪些用户聊天的会话范围。您应该从不将请求或会话范围的数据分配为 servlet 的实例变量。仅在 doGet()doPost() 方法内工作。
【解决方案2】:

这是一种粗略的方法,但我找不到可行的解决方案。我所做的是让所有用户连接到具有 broadcastAll 代码的 servlet。 每个用户都会知道它正在与哪个其他用户聊天。因此,在发送消息时,用户会将他的姓名和正在与之聊天的用户的姓名附加到消息中。由于它是一个 broadcastAll 代码,因此每个连接的用户都会收到该消息。用户收到消息后,会解析消息以获取发送消息的用户,以及消息的目标用户名称。它会将这两个名称与它的记录进行比较——参见前面的粗体声明。如果匹配,它将显示消息,否则忽略它。

同样,这是一种粗略的方法,我相信那里有更好的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    相关资源
    最近更新 更多