为什么在这个Java实现的测验中客户端没有获得下一个问题?

huangapple go评论76阅读模式
英文:

Why doesn't client get next question in this quiz implementation in Java?

问题

这段代码能够正常工作,因为在 UserThread 类中的注释部分被移除后,while 循环正常运行,但当我移除这个注释时,客户端不再接收下一个问题。while 循环在这里停止了。我能否知道发生这种情况的原因?

以下是你提供的代码的翻译:

package quiz;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

public class Server {
    public static int test_port = 12321;
    private int port;
    private int counter = 0;
    private int length;
    BufferedReader fromDocument;
    public int numberOfClients = 0;
    public static HashMap<Integer, List<String>> lista = new HashMap<Integer, List<String>>();

    public static void main(String[] args) {
        Server server = new Server(test_port);
        int l = server.lengthHashMap();
        for (int i = 1; i < l; i++) {
            lista.put(i, null);
        }
        server.execute();
    }

    private void execute() {
        try (ServerSocket server = new ServerSocket(port)) {

            while (true) {
                Socket client = server.accept();
                System.out.println("Client connected");
                numberOfClients++;
                UserThread user = new UserThread(client, this);
                user.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Server(int port) {
        this.port = port;
    }

    private int lengthHashMap() {
        try {
            fromDocument = new BufferedReader(new InputStreamReader(new FileInputStream("Questions.txt")));
            String line = fromDocument.readLine();
            while (line != null) {
                counter++;
                line = fromDocument.readLine();
            }
            length = counter / 5;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return length;
        }
    }
}
package quiz;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;
import java.util.Map.Entry;

public class UserThread extends Thread {
    Socket client;
    Server server;
    BufferedReader fromDocument;
    private int counter = 0;
    PrintWriter toUser;
    BufferedReader fromUser;
    String correctAnswer;
    String answer;
    String correctedLine;
    private int c = 0;

    public UserThread(Socket client, Server server) {
        this.client = client;
        this.server = server;
    }

    public void run() {
        try {

            while (server.numberOfClients < 2) {
                System.out.println();
            }

            fromDocument = new BufferedReader(new InputStreamReader(new FileInputStream("Questions.txt")));
            fromUser = new BufferedReader(new InputStreamReader(this.client.getInputStream()));
            toUser = new PrintWriter(this.client.getOutputStream(), true);
            String line = fromDocument.readLine();
            String name = fromUser.readLine();
            System.out.println(name);
            while (!line.equalsIgnoreCase("")) {
                while (counter < 5) {
                    counter++;
                    if (line.endsWith("*")) {
                        correctAnswer = line.substring(0, 1);
                        correctedLine = line.substring(0, line.length() - 1);
                        toUser.println(correctedLine);
                    } else {
                        toUser.println(line);
                    }
                    line = fromDocument.readLine();

                }
                c++;
                counter = 0;
                answer = fromUser.readLine();


                if (answer.equalsIgnoreCase(correctAnswer))
                    toUser.println("Correct!");
                else
                    toUser.println("Incorrect!");

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
package quiz;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
    private String name;
    private String hostname;
    private int port;
    String answer;
    BufferedReader fromServer;
    PrintWriter toServer;

    public static void main(String[] args) {
        Client client = new Client("localhost", Server.test_port);
        client.execute();
    }

    private void execute() {
        try {
            this.setName();
        } catch (IOException e) {
            e.printStackTrace();
        }

        try (Socket client = new Socket(this.hostname, this.port)) {

            fromServer = new BufferedReader(new InputStreamReader(client.getInputStream()));
            toServer = new PrintWriter(client.getOutputStream(), true);
            System.out.println("Connected to server: " + this.hostname);
            toServer.println(this.name);
            String line;
            while (true) {
                for (int i = 0; i < 5; i++) {
                    line = fromServer.readLine();
                    System.out.println(line);
                }
                System.out.println("Your answer is: ");
                Scanner sc = new Scanner(System.in);
                answer = sc.nextLine();
                toServer.println(answer);
                line = fromServer.readLine();
                System.out.println(line);

            }

        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public Client(String hostname, int port) {
        this.hostname = hostname;
        this.port = port;
    }

    private void setName() throws IOException {
        System.out.println("Enter your name: ");
        BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
        this.name = stdin.readLine();
    }
}

Questions.txt 文件内容:

1. Ko je režirao film Kad jaganjci utihnu?
A) Robert Zemekis
B) Frenk Darabont
C) Džonatan Dem *
D) Rob Rajner
2. U kojoj državi se nalazi jezero Retba? 
A) U Senegalu * 
B) U Ugandi
C) U Gani 
D) U Nigeriji 
3. Kako se zove drugi studijski album grupe Zabranjeno pušenje?
A) Dok čekaš sabah sa šejtanom * 
B) Male priče o veliko ljubavi 
C) Pozdrav iz zemlje Safari 
D) Fildžan viška 
4. Pod kojom zastavom nastupa teniser Alehandro Davidovič Fokina? 
A) Pod zastavom Argentine 
B) Pod zastavom Rusije 
C) Pod zastavom Velike Britanije 
D) Pod zastavom Španije *
英文:

This code works, because while loop is working, but when I remove this comment in UserThread class

/*	for(Entry&lt;Integer,List&lt;String&gt;&gt; m: server.lista.entrySet()) {
if(c==m.getKey()) {
m.getValue().add(name);
//toUser.println(&quot;&quot;);
}
}
for(Entry&lt;Integer,List&lt;String&gt;&gt; m: server.lista.entrySet()) {
System.out.println(m.getKey()+&quot; &quot;+m.getValue());
}*/

client doesn't receive next question. While loop is stopping here. Can I get reason why this is happening?
Codes are below.

package quiz;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
public class Server {
public static int test_port=12321;
private int port;
private int counter=0;
private int length;
BufferedReader fromDocument;
public int numberOfClients=0;
public static HashMap&lt;Integer,List&lt;String&gt;&gt; lista=new HashMap&lt;Integer,List&lt;String&gt;&gt;();
public static void main(String[] args) {
//int l=lengthHashMap();
// TODO Auto-generated method stub
Server server=new Server(test_port);
int l=server.lengthHashMap();
for(int i=1;i&lt;l;i++) {
lista.put(i, null);
}
server.execute();
}
private void execute() {
// TODO Auto-generated method stub
try(ServerSocket server=new ServerSocket(port)){
while(true) {
Socket client=server.accept();
System.out.println(&quot;Client connected&quot;);
numberOfClients++;
UserThread user=new UserThread(client,this);
user.start();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Server(int port) {
this.port=port;
}
private int lengthHashMap() {
try {
fromDocument=new BufferedReader(new InputStreamReader(new FileInputStream(&quot;Questions.txt&quot;)));
String line=fromDocument.readLine();
while(line!=null) {
counter++;
line=fromDocument.readLine();
}
length=counter/5;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
return length;
}
}
}
package quiz;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.List;
import java.util.Map.Entry;
public class UserThread extends Thread{
Socket client;
Server server;
BufferedReader fromDocument;
private int counter=0;
PrintWriter toUser;
BufferedReader fromUser;
String correctAnswer;
String answer;
String correctedLine;
private int c=0;
public UserThread(Socket client, Server server) {
// TODO Auto-generated constructor stub
this.client=client;
this.server=server;
}
public void run() {
try {
while(server.numberOfClients&lt;2) {
System.out.println();
}
fromDocument=new BufferedReader(new InputStreamReader(new FileInputStream(&quot;Questions.txt&quot;)));
fromUser=new BufferedReader(new InputStreamReader(this.client.getInputStream()));
toUser=new PrintWriter(this.client.getOutputStream(),true);
String line=fromDocument.readLine();
String name=fromUser.readLine();
System.out.println(name);
while(!line.equalsIgnoreCase(&quot;&quot;)) {
while(counter&lt;5) {
counter++;
if(line.endsWith(&quot;*&quot;)){
correctAnswer=line.substring(0,1);
correctedLine=line.substring(0,line.length()-1);
toUser.println(correctedLine);
}
else {
toUser.println(line);	
}
line=fromDocument.readLine();
}
c++;
counter=0;
answer=fromUser.readLine();
if(answer.equalsIgnoreCase(correctAnswer))
toUser.println(&quot;Correct!&quot;);
else
toUser.println(&quot;Incorrect!&quot;);
//line=fromUser.readLine();
//System.out.println(line);
/*	for(Entry&lt;Integer,List&lt;String&gt;&gt; m: server.lista.entrySet()) {
if(c==m.getKey()) {
m.getValue().add(name);
//toUser.println(&quot;&quot;);
}
}
for(Entry&lt;Integer,List&lt;String&gt;&gt; m: server.lista.entrySet()) {
System.out.println(m.getKey()+&quot; &quot;+m.getValue());
}*/
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
package quiz;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client {
private String name;
private String hostname;
private int port;
String answer;
BufferedReader fromServer;
PrintWriter toServer;
public static void main(String[] args) {
// TODO Auto-generated method stub
Client client=new Client(&quot;localhost&quot;,Server.test_port);
client.execute();
}
private void execute() {
try {
this.setName();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// TODO Auto-generated method stub
try(Socket client=new Socket(this.hostname,this.port)){
fromServer=new BufferedReader(new InputStreamReader(client.getInputStream()));
toServer=new PrintWriter(client.getOutputStream(),true);
System.out.println(&quot;Connected to server: &quot;+this.hostname);
toServer.println(this.name);
String line;
while(true) {
for(int i=0;i&lt;5;i++) {
line=fromServer.readLine();
System.out.println(line);
}
System.out.println(&quot;Your answer is: &quot;);
Scanner sc=new Scanner(System.in);
answer=sc.nextLine();
toServer.println(answer);
line=fromServer.readLine();
System.out.println(line);
//toServer.println(&quot;Next&quot;);
//for(int j=0;j&lt;5;j++)
//	line=fromServer.readLine();
}
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public Client(String hostname,int port) {
this.hostname=hostname;
this.port=port;
}
private void setName() throws IOException {
// TODO Auto-generated method stub
System.out.println(&quot;Enter your name: &quot;);
BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
this.name=stdin.readLine();
}
}

Content of file Questions.txt:

1. Ko je režirao film Kad jaganjci utihnu?
A) Robert Zemekis
B) Frenk Darabont
C) Džonatan Dem *
D) Rob Rajner
2. U kojoj državi se nalazi jezero Retba? 
A) U Senegalu * 
B) U Ugandi
C) U Gani 
D) U Nigeriji 
3. Kako se zove drugi studijski album grupe Zabranjeno pušenje?
A) Dok čekaš sabah sa šejtanom * 
B) Male priče o veliko ljubavi 
C) Pozdrav iz zemlje Safari 
D) Fildžan viška 
4. Pod kojom zastavom nastupa teniser Alehandro Davidovič Fokina? 
A) Pod zastavom Argentine 
B) Pod zastavom Rusije 
C) Pod zastavom Velike Britanije 
D) Pod zastavom Španije *

答案1

得分: 1

一个 NullPointerException 在你的代码中出现在这一行:m.getValue().add(name)。这个异常的根本原因在于你的 Server 类。请观察你的 Server 类中的以下代码:

for (int i = 1; i &lt; l; i++) {
    lista.put(i, null);
}

你将每个整数与一个空值关联起来。现在,每当你使用 lista.get(1) 时,它返回 null。当你使用 lista.get(1).add(name) 时会发生什么?它会抛出一个 NullPointerException。这就是为什么 m.getValue().add(name) 抛出 NullPointerException,因为 m.getValue() 为 null。

改进

你的代码充满了糟糕的实践。你应该避免它们,因为这会使代码更难调试、更难阅读,甚至可能影响性能。以下是我观察到的一些问题:

  1. 你的 UserThread 类中没有打印堆栈跟踪。如果你这样做了,你本可以自己找到问题。目前,你的 catch 块是空的。

  2. port 变量可以是 final 和 static。服务器将在一个固定的端口上工作,它与整个服务器实例相关,而不是特定的服务器对象实例。因此,它可以是 final 和 static。

  3. 从 finally 块中返回。这是一个非常糟糕的实践,有很多原因。你可以在线搜索了解更多信息。

  4. While 循环语句无法完成而不抛出异常。你的循环是无限的,只有在发生异常时才能结束。你可以在客户端上添加一个优雅的结束。它可以在回答所有问题后结束。

可能还有一些其他较小的改进,但我会保持列表的简洁。

英文:

A NullPointerException occurs in your code at the line m.getValue().add(name). The root cause of this exception is in your Server class. Observe the following code from your Server class:

for (int i = 1; i &lt; l; i++) {
lista.put(i, null);
}

You associate each Integer to a null value. Now, whenever you will use lista.get(1) it returns null. What happens when you use lista.get(1).add(name)? It throws a NullPointerException. That is why m.getValue().add(name) throws NullPointerException, since m.getValue() is null.

Improvements

Your code is filled with bad practices. You should avoid them as this makes code harder to debug, less readable and can even impact performance. Here are few things that I have observed:

  1. You did not print the stack trace in your UserThread class. You would have caught the problem by yourself if you would have done so. Currently, your catch block is just empty.

  2. port variable can be final and static. Server will work on a fixed port and it is associated to a server as a whole and not a particular instance of server object. Hence, it can be final and static.

  3. Returning from finally block. This is a very bad practice and for several reasons. You can search about it online to know more.

  4. While statement could not complete without throwing exception. Your loop is infinite and it can only end whenever an exception occurs. You can add graceful ending at the client. It can finish whenever it has answered all the questions.

There could be few other minor improvements but I will keep the list short.

huangapple
  • 本文由 发表于 2023年6月26日 22:03:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76557421.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定