2009-10-18 196 views
1

供參考這是作業。我必須建立一個Java Chat服務器。我已經能夠建立一個與1個客戶端通信的服務器。但我需要這個與多個用戶溝通。Java聊天服務器

用戶應該輸入他想與之通話的人的姓名,然後輸入破折號( - ),然後輸入要發送的消息。我可以讓用戶登錄,但我無法獲得要打印的用戶列表或發送給其他用戶的消息。這裏是服務器代碼:

/** 
    Threaded Server 
*/ 

import java.net.ServerSocket; 
import java.net.Socket; 
import java.util.Scanner; 
import java.io.PrintWriter; 
import java.util.HashMap; 
import java.util.Set; 

public class ThreadedServer 
{ 
    public static void main(String[] args) throws Exception 
    { 
     HashMap<String, Socket> users = new HashMap<String, Socket>(); 
     ServerSocket server = new ServerSocket(5679); 
     System.out.println("THE CHAT SERVER HAS STARTED! =)"); 
     while(true) 
     { 
      Socket client = server.accept(); 
      ThreadedServer ser = new ThreadedServer(); 
      ClientFromThread cft =ser.new ClientFromThread(client); 
      String name = cft.getUserName(); 
      users.put(name, client); 
      cft.giveUsersMap(users); 
      //cft.giveOnlineUsers(); //DOES NOT WORK YET!!!! 
      System.out.println("Threaded server connected to " 
         + client.getInetAddress() + " USER: " + name);    
     } 

    } 

    //*************************************************************************************************** 

    class ClientFromThread extends Thread 
    { 
     private Socket client; 
     private Scanner fromClient; 
     private PrintWriter toClient; 
     private String userName; 
     HashMap<String, Socket> users; 

     public ClientFromThread(Socket c) throws Exception 
     { 
      client = c; 
      fromClient = new Scanner(client.getInputStream()); 
      toClient = new PrintWriter(client.getOutputStream(), true); 
      userName = getUser(); 
      start(); 
     } 
     public void giveUsersMap(HashMap<String, Socket> users) 
     { 
      this.users = users; 
     } 

     //THIS DOESNT WORK YET... IT PRINTS THE FIRST LINE BUT NOT THE LIST 
     public void giveOnlineUsers() 
     { 
      toClient.println("These users are currently online:"); 
      Set<String> userList = users.keySet(); 
      String[] userNames = null; 
      userList.toArray(userNames); 

      for(int i = 0; i< userNames.length; i++) 
      { 
       toClient.println(userNames[i]); 
      } 
     } 

     public String getUserName() 
     { 
      return userName; 
     } 

     private String getUser() 
     { 
      String s = ""; 
      while((s.length() < 1) || (s == null)) 
      { 
       toClient.println("What is your first name? "); 
       s=fromClient.nextLine().trim(); 
      } 
      toClient.println("Thank You! Welcome to the chat room " + s + "."); 
      return s.toUpperCase(); 
     } 

     public void run() 
     { 
      String s = null; 
      String toUser; 
      String mesg; 

      while((s=fromClient.nextLine().trim()) != null) 
      { 
       if(s.equalsIgnoreCase("END")) break; 

       for(int i=0; i<s.length(); i++) 
       { 
        if(s.charAt(i) == '-') 
        { 
         toUser = s.substring(0, i).trim().toUpperCase(); 
         mesg = s.substring(i+1).trim(); 
         Socket client = users.get(toUser); 
         try 
         { 
          ClientToThread ctt = new ClientToThread(client); 
          ctt.sendMesg(mesg, toUser); 
          ctt.start(); 
         } 
         catch(Exception e){e.printStackTrace();} 
         break; 
        } 
        if((i+1) == s.length()) 
        { 
         toClient.println("Sorry the text was invalid. Please enter a user name " + 
                "followed by a dash (-) then your message."); 
        } 
       } 
      } 
      try 
      { 
       fromClient.close(); 
       toClient.close(); 
       client.close(); 
      } 
      catch(Exception e){e.printStackTrace();} 
     } 

    } //end class ClientFromThread 

    //*************************************************************************************************** 

    class ClientToThread extends Thread 
    { 
     private Socket client; 
     private PrintWriter toClient; 
     private String mesg; 

     public ClientToThread(Socket c) throws Exception 
     { 
      client = c; 
      toClient = new PrintWriter(client.getOutputStream(), true); 
     } 

     public void sendMesg(String mesg, String userName) 
     { 
      this.mesg = userName + ": " + mesg; 
     } 
     public void run() 
     { 
      toClient.println(mesg); 

      try 
      { 
       toClient.close(); 
       client.close(); 
      } 
      catch(Exception e){e.printStackTrace();} 
     } 

    } //end class ClientToThread 

    //*************************************************************************************************** 

} //end class ThreadedServer 

這裏是客戶機代碼」

import java.net.Socket; 
import java.io.BufferedReader; 
import java.io.InputStreamReader; 
import java.io.PrintWriter; 


public class ReverseClient 
{ 
public static void main(String[] args) throws Exception 
{ 
    String line = null; 
    Socket server= new Socket("10.0.2.103", 5679); 
    System.out.println("Connected to host: " + server.getInetAddress()); 
    BufferedReader fromServer = new BufferedReader(
       new InputStreamReader(server.getInputStream())); 
    PrintWriter toServer = new PrintWriter(server.getOutputStream(), true); 
    BufferedReader input = new BufferedReader( 
       new InputStreamReader(System.in)); 
    while((line=input.readLine()) !=null) 
    { 
     toServer.println(line); 
     System.out.println(fromServer.readLine()); 
    } 
    fromServer.close(); 
    toServer.close(); 
    input.close(); 
    server.close(); 

} 
} 

這裏是控制檯輸出(頂部服務器,底部是客戶端): alt text http://img269.imageshack.us/img269/4037/comandpromp.jpg

我收到錯誤消息(如上圖所示),並且消息沒有發送。關於如何處理這些問題的任何建議?

+0

我收到錯誤(如上圖所示),並且郵件未發送。有關如何處理這些問題的任何建議 – 2009-10-18 02:37:19

+0

發佈客戶端代碼,所以我可以嘗試讓這個示例運行並嘗試幫助您。 – delux247 2009-10-18 02:45:22

+0

我添加了客戶端代碼。您將需要更改IP地址以適應您的網絡。 – 2009-10-18 02:48:01

回答

1

到目前爲止,我發現這是一個問題,但我不認爲這是唯一的問題..

這將有助於NoSuchElementException異常 圍繞線90改變了...

while((s=fromClient.nextLine().trim()) != null) 
{ 

這個...

while(fromClient.hasNext()) 
{ 
    s = fromClient.nextLine().trim(); 

OK剛剛發現的另一個問題ClientToThread.run()...你是關閉客戶端連接後,您發送的第一messag即我把它們都評論了出來,看起來好像工作得更好一些。

public void run() 
    { 
    toClient.println(mesg); 
    try { 
     //toClient.close(); 
     //client.close(); 
    } 
    catch (Exception e) { 
     e.printStackTrace(); 
    } 
    } 
+0

好的。我修正了這一點。我不相信我沒有接受。這部分是從我的教授給出的例子中複製而來的。 – 2009-10-18 03:16:36

+0

現在我得到... java.net.SocketException:軟件導致連接中止:recv失敗在ReverseClient的這一行上... System.out.println(fromServer.readLine()); – delux247 2009-10-18 03:18:14

+0

好的。這照顧到了錯誤......現在消息正在發送,但它們並沒有按照它們發送的順序發送給接收方......並且接收方直到發送消息纔得到它...... – 2009-10-18 14:53:52

0

Your fir問題在於解析來自用戶的消息。

通過字符串循環,它有兩個選項之一,無論是字符是短劃線還是無效。

因此,理想情況下,您應該在短劃線之前獲取用戶名中字符數的無效消息。

您應該使用String.indexOf來確定短劃線的位置,然後將消息拆分爲兩部分,如果indexOf的結果爲-1,那麼它是無效的消息。