2011-12-29 147 views
1

嗨有人可以幫我用這段代碼,因爲我正在嘗試使用If語句,但沒有工作。我不是要求爲我寫代碼,而是指向我一些東西。聊天服務器。線程問題

主要問題是,每次有人連接時,都會創建新的線程,但是當他關閉聊天框時,踏板會保持打開狀態並且不能正常工作。我的意思是有些身體自己做了10個連接,沒有其他人可以聊天。

import java.net.*; 
import java.io.*; 

public class myServer { 

    static ServerSocket server; 
    static Socket client; 
    static DataInputStream in; 
    static DataOutputStream out; 
    static clientThread t[] = new clientThread[10]; 

    public static void main(String[] args) throws IOException { 

     System.out.println("Starting Server"); 
     server = new ServerSocket(7555); 
     System.out.println("Started Server"); 

     while (true) { 

      client = server.accept(); 
      System.out.println("CONNECTION"); 
      out = new DataOutputStream(client.getOutputStream()); 
      out.writeUTF("Welcome to the chat room"); 
      for (int i = 0; i <= 9; i++) { 
       if (t[i] == null) { 
        (t[i] = new clientThread(client, t)).start(); 
        break; 
       } 
      } 
     } 

    } 

} 

class clientThread extends Thread { 

    DataInputStream in; 
    DataOutputStream out; 
    static String msg; 
    Socket client = null; 
    clientThread t[]; 

    public clientThread(Socket client, clientThread[] t) { 
     this.client = client; 
     this.t = t; 
    } 

    public void run() { 

     try { 
      in = new DataInputStream(client.getInputStream()); 
      out = new DataOutputStream(client.getOutputStream()); 
      boolean tru = true; 

      while (tru) { 
       msg = in.readUTF(); 
       System.out.println(msg); 
       for (int i = 0; i <= 9; i++) 
        if (t[i] != null) { 
         t[i].out.writeUTF(msg); 
         System.out.println(t[i]); 
        } 
      } 
     } catch (IOException e) { 
     } 
    } 
} 

回答

1

問題不在線程停留,而是您沒有任何機制將客戶線程標記爲完成。即使線程退出,t[i]也不會變爲null。它仍然會引用一個線程的實例 - 只是一個「死」的線程。

下面的兩種方法來解決這個問題:

  1. 只是你的線程退出之前,標記t[i] = null(其中i是當前線程的指數)。請注意,您需要在每個線程中存儲值i

    1. 修改clientThread並添加private int threadIndex;作爲成員變量。
    2. 修改clientThread的構造函數並添加threadIndex作爲參數。

      public clientThread(Socket client, clientThread[] t, int threadIndex) 
      { 
          this.threadIndex=threadIndex; 
          //... 
      } 
      
    3. run右括號之前,加

      synchronized(t){t[this.threadIndex]=null;} 
      
  2. 使用Executor並提交您clientThread s到它。 Java的Executor s將爲您處理清理線程。

0

您可以調用方法client.getOutputStream()兩次,每次構建一個DataOutputStream。嘗試直接在ClientThread中歡迎用戶。

1

爲什麼只爲一個套接字連接創建10個線程?我想你想創建一個ClientThread每個傳入連接到聊天服務器。然後將該單個ClientThread添加到活動聊天列表中。聊天客戶端終止會話時,從該列表中刪除條目。您不需要將Thread實例或ClientThread的數組傳遞給ClientThread的構造函數,因爲它本身就是這樣。只需將Socket實例傳遞給ClientThread以及對ChatServer的引用即可。如果您嘗試創建聊天室。然後讓服務器來處理髮送消息給其他人:

public class ChatServer { 
    List<ClientThread> activeParticipants; 

    public void say(ClientThread author, String message) { 
     for(ClientThread current : activeParticipants) { 
      if(current != author) { 
       current.send(message); // this method will send a message to that client 
      } 
     } 
    } 
} 

你要麼需要使用兩個線程,或者使用InputStream.available()方法來檢查,看看是否有輸入的任何系統。在你的套接字的輸入流中。這將允許您閱讀消息,並允許用戶同時輸入消息。在read()方法上阻塞意味着在輸入一些數據或接收數據之前,您看不到消息。

還要將歡迎消息移動到ClientThread中,以便不使用兩個不同的DataOutputStream調用Socket.getOutputStream()兩次。