2012-05-17 95 views
-4

下面是处理多用户聊天的客户端和服务器的代码。但是当一个客户端写入“退出”时,其他当前连接的客户端也终止,并且我不能连接另一个客户端。任何人都可以帮忙吗?Java多线程多客户端错误

这里是我的客户端代码:

class TCPClientsc { 
    public static void main(String argv[]) throws Exception { 
     String modifiedSentence; 
     InetAddress inetAddress = InetAddress.getLocalHost(); 
     System.out.println(inetAddress); 

     Socket clientSocket = new Socket(inetAddress, 6789); 
     DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream()); 

     BufferedReader inFromServer = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); 

     CThread write = new CThread(inFromServer, outToServer, 0, clientSocket); 
     CThread read = new CThread(inFromServer, outToServer, 1, clientSocket); 
    } 
} 

class CThread extends Thread { 
    BufferedReader inFromServer; 
    DataOutputStream outToServer; 
    Socket clientSocket = null; 
    int RW_Flag; 
    public CThread(BufferedReader in, DataOutputStream out, int rwFlag, Socket clSocket) { 
     inFromServer = in; 
     outToServer = out; 
     RW_Flag = rwFlag; 
     clientSocket = clSocket; 
     start(); 
    } 
    public void run() { 
     String sentence; 
     try { 
      while (true) { 
       if (RW_Flag == 0) {// write 
        BufferedReader inFromUser = new BufferedReader(new InputStreamReader(System.in)); 
        sentence = inFromUser.readLine(); 

        // System.out.println("Writing "); 
        outToServer.writeBytes(sentence + '\n'); 
        if (sentence.equals("quit")) 
         break; 

       } else if (RW_Flag == 1) { 
        sentence = inFromServer.readLine(); 
        if (sentence.endsWith("quit")) 
         break; 
        System.out.println("(received)" + sentence); 
       } 
      } 
     } catch (Exception e) { 
     } finally { 
      try { 
       inFromServer.close(); 
       outToServer.close(); 
       clientSocket.close(); 

      } catch (IOException ex) { 
       Logger.getLogger(CThread.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 
} 

Server代码:

class TCPServersc { 
    static int i = 0; 
    static SThread tt[] = new SThread[100]; 
    static SThread anot[] = new SThread[100]; 
    public static void main(String argv[]) throws Exception { 
     String client; 
     String capitalizedSentence; 
     ServerSocket welcomeSocket = new ServerSocket(6789); 

     while (true) { 
      Socket connectionSocket = welcomeSocket.accept(); 
      i++; 
      System.out.println("connection :" + i); 
      BufferedReader inFromClient = new BufferedReader(newInputStreamReader(connectionSocket.getInputStream())); 
      DataOutputStream outToClient = new DataOutputStream(connectionSocket.getOutputStream()); 
      BufferedReader inFromMe = new BufferedReader(new InputStreamReader(System.in)); 

      tt[i] = new SThread(inFromClient, outToClient, tt, 0, connectionSocket, i); 
      anot[i] = new SThread(inFromMe, outToClient, tt, 1, connectionSocket, i); 
     } 
    } 
} 

// =========================================================== 
class SThread extends Thread { 
    BufferedReader inFromClient; 
    DataOutputStream outToClient; 
    String clientSentence; 
    SThread t[]; 
    String client; 
    int status; 
    Socket connectionSocket; 
    int number; 

    public SThread(BufferedReader in, DataOutputStream out, SThread[] t, int status, Socket cn, int number) { 
     inFromClient = in; 
     outToClient = out; 
     this.t = t; 
     this.status = status; 
     connectionSocket = cn; 
     this.number = number; 
     start(); 
    } 

    public void run() { 
     try { 
      if (status == 0) { 
       clientSentence = inFromClient.readLine(); 
       StringTokenizer sentence = new StringTokenizer(clientSentence, " "); 

       // /////////////////////////////////////////////////////////// 
       if (sentence.nextToken().equals("login")) { 
        String user = sentence.nextToken(); 
        String pass = sentence.nextToken(); 
        FileReader fr = new FileReader("file.txt"); 
        BufferedReader br = new BufferedReader(fr); 
        int flag = 0; 
        while ((client = br.readLine()) != null) { 
         if ((user.equals(client.substring(0, 5))) && (pass.equals(client.substring(6, 10)))) { 
          flag = 1; 
          System.out.println(user + " has logged on"); 
          for (int j = 1; j <= 20; j++) { 
           if (t[j] != null) 
            t[j].outToClient.writeBytes(user + " has logged on" + '\n');// '\n' is necessary 
          } 
          break; 
         } 
        } 
        if (flag == 1) { 
         while (true) { 
          clientSentence = inFromClient.readLine(); 
          System.out.println(user + " : " + clientSentence); 
          for (int j = 1; j <= 20; j++) { 
           if (t[j] != null) 
            // '\n' is necessary 
            t[j].outToClient.writeBytes(user + " : " + clientSentence + '\n'); 
          } 
          // if(clientSentence.equals("quit"))break; 
         } 
        } 
       } 
      } 
      // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
      if (status == 1) { 
       while (true) { 
        clientSentence = inFromClient.readLine(); 
        if (clientSentence.equals("quit")) 
         break; 

        System.out.println("Server: " + clientSentence); 
        for (int j = 1; j <= 20; j++) { 
         if (t[j] != null) 
          t[j].outToClient.writeBytes("Server :" + clientSentence + '\n');// '\n' is necessary 
        } 
       } 
      } 
     } catch (Exception e) { 
     } finally { 
      try { 
       // System.out.println(this.t); 
       inFromClient.close(); 
       outToClient.close(); 
       connectionSocket.close(); 
      } catch (IOException ex) { 
       Logger.getLogger(SThread.class.getName()).log(Level.SEVERE, null, ex); 
      } 
     } 
    } 
} 
+0

推测问题出在服务器上,而不是客户端上,因为一个客户端可能会影响到另一个客户端。我们必须看到服务器代码。 –

+4

请格式化您的代码并删除注释掉的语句。如果你问别人花时间读你的代码,你应该愿意让它可读。 –

+0

我们不倾向于通过你的丰富和格式不正确的代码。减少并格式化,然后你*有机会 – Bohemian

回答

1

此代码有很多问题。

  • 首先,在未来,请张贴是很好的格式化,简洁的代码片段。我只是基本上重新格式化您的文章中的所有内容。
  • 我看到几个地方你正在捕捉异常,但什么都不做。这是巨大的不好的做法。至少你应该打印/记录你捕捉到的异常。我怀疑这是造成你的问题。
  • 我觉得RW_Flag很混乱。那么你应该有两个客户端线程。一个从System.in写入服务器,另一个读取。没有一个客户端线程做2件事。与服务器中的status标志相同。这应该是2个不同的线程。
  • 而不是服务器中的int flag = 0;,应该是boolean loggedIn;。在Java中使用布尔值代替C风格的标志并使用更好的变量名称。代码可读性将为自己付出代价。 statusRW_flag等。
  • 代替巨大的代码块,您应该将连续代码移出方法:handleSystemIn(),handleClient(),talkToServer()。一旦你在你的代码中创建了更多的方法,并缩减了各个代码块,它就使得它更具可读性/可调试性/可理解性。
  • 您需要在该数组的每个用法周围有一个synchronized (tt)块。一旦有多个线程全部使用tt如果主线程accept添加到线程中,则需要同步更新。

我没有立即看到这个问题虽然通心粉代码是太难以解析。我怀疑你在某处抛出和异常,这是客户在第一个客户退出后无法连接的原因。除此之外,我会继续使用System.out.println自由使用调试来查看哪些消息正在发送到哪里。