【问题标题】:multi client error with java multithreadingjava多线程的多客户端错误
【发布时间】:2012-05-17 04:32:36
【问题描述】:

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

这是我的客户端代码:

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

【问题讨论】:

  • 可能问题出在服务器上,而不是客户端,因为一个客户端会影响另一个客户端。我们必须查看服务器代码。
  • 请以可读的方式格式化您的代码并删除注释掉的语句。如果你让别人花时间阅读你的代码,你应该愿意让它可读。
  • 我们不希望涉足您大量且格式错误的代码。将其缩小并格式化,然后您可能有机会

标签: java multithreading client chat


【解决方案1】:

这段代码有很多问题。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-11
    • 2015-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多