2011-12-29 5 views
1

안녕하세요 누군가 내가이 문장으로 노력하고 있었기 때문에이 코드로 나를 도울 수는 있었지만 작동하지 않습니다. 나는 나를 위해 코드를 써달라고 요청하지 않고있다.채팅 서버. 스레드 문제

주요 문제는 누군가가 연결될 때마다 새 스레드가 만들어 지지만 채팅 상자를 끄면 트레드가 계속 켜져 있어야하며 작동하지 않아야한다는 것입니다. 내 말은 어떤 몸이 직접 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가 현재의 thread의 인덱스입니다) :

    여기의 그것을 해결하는 방법은 두 가지입니다. 각 스레드에 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의를 제출합니다. Java의 Executor는 스레드 정리를 처리합니다.

0

DataOutputStream을 빌드 할 때마다 메소드 client.getOutputStream()을 두 번 호출합니다. ClientThread에서 직접 사용자를 환영하십시오.

1

단 하나의 소켓 연결에 대해 10 개의 스레드를 생성하는 이유는 무엇입니까? 채팅 서버에 들어오는 연결마다 하나의 ClientThread를 만들고 싶습니다. 그런 다음 해당 단일 ClientThread를 활성 채팅 목록에 추가하십시오. 채팅 클라이언트가 세션을 종료하면 해당 목록에서 항목을 제거하십시오. ThreadTemplate의 인스턴스를 ClientThread의 생성자에 전달할 필요가 없으므로 ThreadTemplate의 인스턴스 나 ClientThreads의 배열을 ClientThread의 생성자에 전달할 필요가 없습니다. ClientThread에 Socket 인스턴스를 전달하고 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() 메소드를 사용해야 하나. in 또는 소켓의 입력 스트림. 그러면 사용자가 들어오는 메시지를 읽을 수있을뿐 아니라 동시에 메시지를 입력 할 수 있습니다. read() 메소드를 차단하면 일부 데이터를 입력하거나 데이터를 수신 할 때까지는 메시지를 볼 수 없습니다.

두 개의 다른 DataOutputStream을 사용하여 Socket.getOutputStream()을 두 번 호출하지 않도록 환영 메시지를 ClientThread로 이동하십시오.