如何使用applet和servlet在两个客户端和两个客户端之间启动聊天?

时间:2010-04-02 15:09:36

标签: java http servlets applet chat

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

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

  1. 我创建了一个具有'broadcast-all'代码的servlet实例。
  2. 然后我将此实例的地址传递给相应的客户。
  3. 2个客户端小程序使用该地址进行聊天。从技术上讲,代码是'broadcast-all',但由于只有2个客户端连接到它,它提供了两个客户端功能之间的聊天。因此,2个客户端的组具有相同servlet的不同实例,并且每个实例最多处理两个客户端之间的聊天。
  4. 然而,正如预测的那样,这个想法没有实现!

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

      

    我现在知道如何使用request.getSession()。因此,我在其param标记中为applet设置会话,并将其用于与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;
    }
    }
    
      

    在applet方面,我有一个线程,它将使用GET方法连接到上面的servlet以获取新消息。它使用while循环,并阻塞,直到它从servlet获取消息。每当客户端输入消息时,主线程使用POST方法与servlet通信。目前所有客户都与大家聊天。我想使用上面使用的相同方法(或者如果可能的话,使用任何其他方式)在两个客户端和两个客户端之间建立聊天。我可能在applet中有另一个线程来检查是否有其他用户希望与它聊天,然后交换一些数据,以便只有那两个用户聊天......

    然后我尝试修改我的广播所有代码。在该代码中,我使用的是实现Observer和Observable接口的类。所以我得到的下一个想法是:

    1. 创建Observable类的新对象(比如class_1)。这个对象对2个客户来说很常见。
    2. 2个希望聊天的客户将使用class_1的相同对象。
    3. 其他2个客户端将使用class_1的其他对象。
    4. 但问题在于实现Observer接口的类(比如class_2)。由于这有观察者监视同一类型的类,即class_1,如何建立监视class_1的一个对象的观察者和另一个监视同一类class_1的另一个对象的观察者(因为notifyObservers()会通知所有观察者,我可以' t将特定观察者分配给特定对象)?

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

      此致 大额牛

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

2 个答案:

答案 0 :(得分:2)

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

通过这种方式,您可以了解哪些用户都可用,哪些用户在当前会话中以及与哪些用户单独聊天。

答案 1 :(得分:0)

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

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