2010-04-02 52 views
0

我首先需要爲我以前的問題道歉。 (你可以檢查我的個人資料)他們似乎提出更多的問題,而不是給出答案。因此,我制定了真正的問題,開始了他們所有荒謬的問題。如何僅使用小程序和servlet在兩個客戶端和兩個客戶端之間啓動聊天?

我試圖設計一個聊天小程序。到目前爲止,我已經編寫了applet,servlet和applet和servlet之間的通信。 servlet方面的代碼使我能夠使用applet在客戶端之間建立聊天,但代碼更像是廣播全部功能,即所有的客戶端都將互相聊天。這是我開始設計聊天小程序時的第一個目標。第二步是隻與兩個特定用戶聊天,就像我們其他任何聊天應用程序一樣。所以這是我的想法:

  1. 我創建了具有'全部廣播'代碼的servlet實例。
  2. 我那麼這種情況下的地址傳遞給相應的客戶。
  3. 2個客戶端小程序使用該地址進行聊天。從技術上講,代碼是「全部廣播」,但由於只有2個客戶端連接到它,因此可以在兩個客戶端功能之間進行聊天。因此,2個客戶端組具有相同servlet的不同實例,並且每個實例處理兩個客戶端之間的聊天。

然而,作爲預測,這個想法沒有實現!

我試過來創建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; 
} 
} 

在小程序方面,我有一個線程將連接到該servlet上述使用GET方法來獲得新的消息。它使用一個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 class_1的另一個對象(因爲notifyObservers()會通知所有觀察者,將特定的觀察者分配給特定的對象)?

我首先決定問個人問題,比如如何在stackoverflow中使用observable和observer等對象來創建servlet的實例......但我更加困惑。任何人都可以給我一個想法如何建立兩個客戶端之間的聊天?(我使用Http而不是套接字或RMI)。

Regards, Mithun。

P.S.感謝所有回覆我以前(荒謬)查詢的人。我應該在早些時候說明這個目的,這樣你們才能更好地幫助我。

+1

在發佈此問題之前,您是否閱讀過我的回答? http://stackoverflow.com/questions/2566496/can-an-applet-communicate-with-an-instance-of-a-servlet你最好編輯你的原始問題,以包含更多的細節。這兩個問題歸結爲相同。 – BalusC 2010-04-02 15:12:28

+0

是的,我剛剛做到了。它清楚地回答了會議部分。謝謝。但我仍然不明白如何建立兩個客戶端之間的聊天。另外,我將編輯上面的內容以包含更多細節。 – mithun1538 2010-04-02 15:19:13

回答

2

您需要使用ServletContext#setAttribute()將所有連接的用戶存儲在Map<String, User>應用程序範圍內。 String表示唯一的用戶標識符(聊天暱稱?)。您需要使用HttpSession#setAttribute()來存儲特定聊天User以及會話範圍。您還需要將其他用戶保存在Map<String, User>,會話會話範圍內的單個聊天中。您可以通過getAttribute()方法獲取該屬性。

這樣您就知道哪些用戶全部可用,哪些用戶在當前會話中以及與哪些用戶單獨聊天。

+0

在Map 中,「string」是一個客戶端(暱稱)的名稱。什麼是「用戶」?這是「string」正在與之聊天的用戶的名字嗎? – mithun1538 2010-04-02 16:31:28

+0

它應該是一個代表相關客戶/用戶的值對象。它可以包含有關用戶名,IP,其他用戶聊天,歷史等信息,無論你喜歡什麼。你當然也可以只使用用戶名「''。 – BalusC 2010-04-02 17:25:40

+0

好的。直到現在我明白了這一點: 1.在小應用程序方面,我做了您在其他「servlet實例」問題中所要求的更改 2.在servlet方面,我記下了所有連接的用戶。我將使用LIST而不是MAP,並將唯一用戶添加到應用程序上下文中的列表中。 之後,我只是失去你。儘管如此,你已經給了我一個想法,讓我設置會議..我會努力。謝謝 – mithun1538 2010-04-02 17:40:51

0

這是一個粗糙的方法來做到這一點,但我找不到一個可行的解決方案。我所做的是讓所有用戶連接到具有broadcastAll代碼的servlet。 每個用戶都會知道與哪個用戶聊天。因此,在發送消息時,用戶會將他的姓名和他正在聊天的用戶的姓名附加到消息中。由於它是一個broadcastAll代碼,每個連接的用戶都會收到該消息。收到消息後,用戶將解析消息以獲取發送消息的用戶以及消息所針對的用戶的名稱。它會將這兩個名稱與其記錄進行比較 - 請參閱前面粗體的說明。如果匹配,它會顯示消息,否則忽略它。

再一次,它是一個粗略的方法來做到這一點,我相信有更好的解決方案。