2012-01-30 156 views
4

我正在從一個簡單的教程,我發現一個TCP聊天服務器,我是一種新的Java。我最終將創建一個客戶端類,但我一直在通過telnet測試它。我有幾個問題。我已經設置了服務器以從客戶端獲取命令。例如關閉客戶端連接的「EXIT」和打印「OK」的「用戶名」。如下圖所示:簡單的Java聊天服務器

用戶1:TIM

Welcome to Bob's Chat Server! 

Please Enter a User Name: 
Tim 
Welcome Tim we hope you enjoy your chat today 
Bob:Hello 
Hi Bob 
Tim 
OK 
EXIT 
Closing Connection . . . Goodbye 

用戶2:BOB

Welcome to Bob's Chat Server! 

Please Enter a User Name: 
Bob 
Welcome Bob we hope you enjoy your chat today 
Hello 
Tim:Hi Bob 
Tim:Tim 

我有,我想解決三個問題:

  1. 你會注意到,當USER 1 t用戶名「Tim」(他的用戶名),它表示「OK」,就像我想要的一樣,但它也向用戶2打印了「Tim」。是否有辦法讓它不能發送我輸入的命令?所以當我輸入「Tim」時,它不會將「Tim」打印到USER 2?

  2. 當郵件發送給其他用戶時,它顯示誰說的。有沒有辦法在兩個連接上打印名稱?例如,當用戶2說「你好」時,它在兩個連接上看起來更像是「Bob:Hello」?

  3. 是否有一種方法可以跟蹤整個聊天會話中所說的所有內容,並將任何用戶請求的聊天內容打印出來?

這裏是我的服務器代碼:

// Chat Server runs at port no. 9020 
import java.io.*; 
import java.util.*; 
import java.net.*; 
import static java.lang.System.out; 

public class TCPServer 
{ 
    Vector<String> users = new Vector<String>(); 
    Vector<HandleClient> clients = new Vector<HandleClient>(); 

    int PORT = 9020; 
    int NumClients = 10; 

    public void process() throws Exception 
    { 
     ServerSocket server = new ServerSocket(PORT,NumClients); 
     out.println("Server Connected..."); 
     while(true) 
     { 
     Socket client = server.accept(); 
     HandleClient c = new HandleClient(client); 
     clients.add(c); 
    } // end of while 
    } 

    public static void main(String ... args) throws Exception 
    { 
     new TCPServer().process(); 
    } // end of main 

    public void boradcast(String user, String message) 
    { 
     // send message to all connected users 
     for (HandleClient c : clients) 
      if (!c.getUserName().equals(user)) 
      { 
       c.sendMessage(user,message); 
      } 
    } 

    class HandleClient extends Thread 
    { 
    String name = ""; 
    BufferedReader input; 
    PrintWriter output; 

    public HandleClient(Socket client) throws Exception 
    { 
      // get input and output streams 
     input = new BufferedReader(new InputStreamReader(client.getInputStream())) ; 
     output = new PrintWriter (client.getOutputStream(),true); 
     output.println("Welcome to Bob's Chat Server!\n"); 
     // read name 
     output.println("Please Enter a User Name: "); 
     name = input.readLine(); 
     users.add(name); // add to vector 
     output.println("Welcome "+name+" we hope you enjoy your chat today"); 
     start(); 
    } 

    public void sendMessage(String uname,String msg) 
    { 
     output.println(uname + ":" + msg); 
    } 

    public String getUserName() 
    { 
     return name; 
    } 

    public void run() 
    { 
     String line; 
     try  
     { 
      while(true) 
      { 
         line = input.readLine(); 
       if("EXIT".equals(line)) 
      { 
       output.println("Closing Connection . . . Goodbye"); 
          clients.remove(this); 
         users.remove(name); 
       break; 
        } 
      else if(name.equals(line)) 
      { 
          output.println("OK"); 
        } 
       boradcast(name,line); // method of outer class - send messages to all 
      }// end of while 
     } // try 
     catch(Exception e) 
     { 
      System.out.println(e.getMessage()); 
     } 
    } // end of run() 
    } // end of inner class 
} // end of Server 

任何幫助表示讚賞。謝謝。

回答

2

我修改了你的代碼按自己的喜好,做看看:

對於第一點:

public void run() 
    { 
     String line; 
     try  
     { 
      while(true) 
      { 
         line = input.readLine(); 
       if("EXIT".equals(line)) 
       { 
        output.println("Closing Connection . . . Goodbye"); 
        clients.remove(this); 
        users.remove(name); 
        break; 
       } 
       else if(name.equals(line)) 
       { 
        output.println("OK"); 
       } 
       else 
       { 
        // Seems to me just adding this else part will do the trick for point one. 
        boradcast(name,line); // method of outer class - send messages to all 
       } 
      }// end of while 
     } // try 
     catch(Exception e) 
     { 
      System.out.println(e.getMessage()); 
     } 
    } 

對於第2點:

在我看來,在這你打字到控制檯來獲取輸入信息,在這種情況下,只要輸入必須發送到另一端的內容,至少可以在該方法的第一行中添加修改,如broadcast(); ,以便您可以滿足您對第2點的需求,或(其他您可以讓服務器端將其發送回客戶端,包含該名稱的消息,它將像客戶端將其消息發送到服務器,並且服務器將所有客戶端發回。

public void boradcast(String user, String message) 
{ 
    System.out.println(user + " : " + message); 
    // send message to all connected users 
    for (HandleClient c : clients) 
    if (!c.getUserName().equals(user)) 
    { 
     c.sendMessage(user,message); 
    } 
} 

而對於第三點,你可以寫你的談話到文件或將其保存到數據庫中,這曾經的辦法是適當的給你。

既然你說你是Java新手,那麼最好看看java.nio。這個包比以前的java.io包好。

最新編輯:

試試這個小樣本代碼,希望這可以做你問什麼:

import java.io.*; 

public class StringConsole 
{ 
    public static void main(String... args) throws IOException 
    { 
     int count = 0; 
     BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); 
     while (count < 5) 
     { 
      System.out.print("My Name : "); 
      String message = br.readLine(); 
      count++; 
     } 
    } 
} 

希望這可以幫助你以某種方式。

Regards

+0

感謝這些建議,他們幫助了很多。我有一個更快的問題。如何讓它在光標前顯示用戶的名字?例如,在用戶輸入名稱後,光標始終顯示「用戶名:」,然後光標開始後綴。 – user1174834 2012-01-30 04:33:51

+0

@ user1174834:如果你使用控制檯,這有點困難,請檢查我最近的編輯,這可以爲你做些什麼。 Regards – 2012-01-30 05:38:26

+0

感謝您的幫助。 – user1174834 2012-01-30 15:45:04

1

有沒有辦法讓它不發送我輸入的命令?所以當我 鍵入「Tim」時,它不會將「Tim」打印到USER 2?

您已將用戶名存儲在HandleClient中;當它的run方法得到輸入時,它會檢查用戶是否輸入了他的名字。所以如果他這麼做,或者他輸入了一個命令,就不要撥打廣播。

當消息發送給其他用戶時,它顯示誰說的。 有兩種方法可以在兩個連接上打印名稱?例如,當 用戶2說「你好」時,在 連接上看起來更像是「Bob:Hello」?

我見過

大多數聊天客戶端有一個多窗口保持對話和一個小的輸入文字。用戶在小窗口中輸入他的文本,然後服務器將其廣播回給他。因此,服務器可以在廣播前在每條消息前添加用戶名和冒號,這將與用戶在自己的客戶端上輸入的內容分開。

有沒有一種方法來跟蹤所有的這是一個在整個 聊天會話說和打印出來的聊天的全部內容,以任何 用戶請求呢?

當然。隨時隨地將它們全部寫入文件。看看java.io.FileWriter。

+1

有一個簡單的例子[這裏](http://stackoverflow.com/a/3245805/230513)。 – trashgod 2012-01-30 03:29:51