-4

下面是处理多用户聊天的客户端和服务器的代码。但是,当一个客户端写“退出”时,我的其他当前连接的客户端也终止,然后我无法连接另一个客户端。有人可以帮忙吗?

这是我的客户代码:

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);
            }
        }
    }
}

服务器代码:

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);
            }
        }
    }
}
4

1 回答 1

1

这段代码有很多问题。

  • 首先,在未来,请发布格式良好的更小、更简洁的代码片段。我只需要基本上重新格式化您帖子中的所有内容。
  • 我看到几个地方你正在捕捉但除了例外什么都不做。这是非常糟糕的做法。至少您应该打印/记录您捕获的异常。我怀疑这会导致您的问题。
  • 我觉得RW_Flag非常混乱。那么你应该有两个客户端线程。一个用于写入System.in服务器,一个用于读取。没有一个客户端线程可以做两件事。与status服务器中的标志相同。那应该是2个不同的线程。
  • 而不是int flag = 0;在服务器中,应该是boolean loggedIn;. 在 Java 中使用布尔值而不是 C 风格的标志,并使用更好的变量名。代码的可读性会为自己买单。status,RW_flag等也一样。
  • 您应该将连续的代码移到方法中,而不是巨大的代码块:handleSystemIn(), handleClient(), talkToServer(). 一旦您在代码中创建了更多方法,并缩小了各个代码块,它就会使其更具可读性/可调试性/可理解性。
  • 您需要synchronized (tt)围绕该数组的每次使用设置一个块。一旦你有多个线程都在使用tt,如果主accept线程添加到它,更新需要同步。

尽管 spagetti 代码太难解析,但我并没有立即看到问题。我怀疑您在某处抛出异常,这就是客户端在第一个退出后无法连接的原因。除此之外,我将继续自由地使用System.out.println调试来查看哪些消息被发送到哪里。

于 2012-05-17T12:55:09.753 回答