网络编程为什么我的敲门笑话在这里(Java网络代码)不符合顺序?
我正在做一个项目,我修改了sample Java networking code from Oracle,这是一个网络化的敲门笑话应用程序
我想让它自己运行。以下是我修改的KnockServer的代码:
import java.net.*;
public class FixedMessageSequenceServer extends Thread {
private static final Logger logger = LoggerFactory.getLogger("FixedMessageSequenceServer");
public static void main(String[] args) throws IOException , InterruptedException {
logger.debug("This is a DEBUG message in Server ");
int jokeLocation;
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(4444);
} catch (IOException e) {
System.err.println("Could not listen on port: 4444.");
System.exit(1);
}
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
} catch (IOException e) {
System.err.println("Accept failed.");
System.exit(1);
}
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
new InputStreamReader(
clientSocket.getInputStream()));
String inputLine, outputLine;
FixedMessageSequenceProtocol kkp = new FixedMessageSequenceProtocol(1);
outputLine = kkp.processInput(null);
out.println(outputLine);
try{
while ((inputLine = in.readLine()) != null) {
System.out.println(inputLine);
outputLine = kkp.processInput(inputLine);
out.println(outputLine);
if (outputLine.equals("Bye."))
break;
}
}catch(SocketException so) {
try { /* boilerplate code for other functionality I needed*/
} catch (IOException exp ) {
exp.printStackTrace();
}
}
out.close();
in.close();
clientSocket.close();
serverSocket.close();
}
}
以下是我的客户端:
public class FixedMessageSequenceClient {
private static final Logger logger = LoggerFactory.getLogger("FixedMessageSequenceClient");
static String KKJokes[] = { "Who's there?", "Turnip who?", "y",
"Who's there?", "Little Old Lady who?", "y",
/* boilerplate code */
"Who's there?", "Who who", "y"};
public static void main(String[] args) throws IOException {
logger.debug("This is a DEBUG message in Client-Side");
int startPosition = 0;
try {
Scanner scan = new Scanner(new File ("somenumber.txt"));
while(scan.hasNext()) {
startPosition = Integer.parseInt(scan.nextLine());
System.out.println("The start position is : " + startPosition + "! ");
}
} catch (Exception io) {}
Socket kkSocket = null;
PrintWriter out = null;
BufferedReader br = null;
try {
kkSocket = new Socket("localhost", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
br = new BufferedReader( new InputStreamReader ( kkSocket.getInputStream() ));
for (int i = startPosition; i < KKJokes.length ; i++) {
try {
Thread.sleep(1000); }
catch(Exception e){
e.printStackTrace();
}
out.println(KKJokes[i % KKJokes.length ]);
String fromServer = br.readLine();
System.out.println ( fromServer ) ;
}
out.println("Bye");
System.out.println ("Bye" );
out.close();
kkSocket.close();
} catch ( IOException io ){
System.err.println("Calling IO . toString " + io.toString());
System.exit(1);
}
}
最后,我稍微修改了协议。java类(link here at Pastebin )能够采取开玩笑的姿势。这个类只有一个大型的多case if-then循环(几乎像一个复杂的switch语句),负责处理笑话序列
我的问题是,当我运行代码时,顺序不正确。以下是输出时的外观:
The start position is : 3! Knock! Knock! Little Old Lady I didn't know you could yodel! Want another? (y/n) Knock! Knock! Doctor Is there an owl doctor? Want another? (y/n) Knock! Knock! Teacher Teacher who says do ur HW please Want another? (y/n) Knock! Knock! You're supposed to say "Who's there?"! Try again. Knock! Knock! You're supposed to say "Who's there?"! Try again. Knock! Knock! You're supposed to say "Who's there?"! Try again. Knock! Knock! Dog You're supposed to say "Dog who?"! Try again. Knock! Knock! You're supposed to say "Who's there?"! Try again. Knock! Knock! Dog You're supposed to say "Dog who?"! Try again. Knock! Knock!
有关这些类的完整版本,请参见以下pastebin链接:
FixedMessageSequenceProtocol.java
FixedMessageSequenceServer.java
FixedMessageSequenceClient.java
谢谢,有什么建议吗
# 1 楼答案
编辑
帖子中的代码与链接中的代码不匹配。这使得这个问题难以置信地难以回答,并且具有误导性
这也意味着你的问题的原因只是一个打字错误——你的客户机代码中有
"Who's there"
,而不是"Who's there?"
。我把最初的答案留在下面,因为if包含了很好的信息,说明了为什么将这些硬编码字符串放在客户机中是个坏主意。你的代码按我想你的意思循环KKJokes
,但是KKJokes[12]
事件顺序:
客户端初始化时
startPosition
设置为3
,即以"Who's there?"
开头,用于KKJokes
中的小老太太笑话服务器初始化[]并将
currentJoke
设置为1
,即老妇人笑话请注意,客户机将所有服务器消息(
S:
)打印到stdout
,并在OP的输出中复制这些消息原始答案
您的输出出现故障的根本原因是,在您的客户机中,您没有处理从其输入中接收到的内容。因此,无论服务器在做什么,客户端都会继续运行。有时,消息恰好达到了服务器期望的顺序,因此您会得到一些看起来几乎正确的输出,但笑话的顺序是错误的
以下是代码的主要问题:
当客户机从服务器接收到任何消息时,它只是打印它(
fromServer
),它不会处理它,也不会根据接收到的内容更改任何内容。您设置了一个客户端输入流(我想应该是“监听”单词“敲门”)您只需以
1000
毫秒的延迟循环响应,然后等待服务器发送的,然后发送列表中的下一个响应。服务器会正确地响应这些,有时,如果响应恰好是它所等待的(巧合),会讲下一个笑话,有时会告诉你“你应该说谁在那里?!”。如果你看一下你链接到的例子中的code for the client,你会发现它有一行这是客户端在等待来自服务器的信息(线索或提示)。如果它收到
"bye"
,则结束程序,否则发送用户输入。如果要发送自动响应而不是用户输入,你可能需要在你的代码中有一些等价的东西——例如进程fromServer
(可能结合一些状态,告诉你你在笑话中处于哪个阶段——例如线索阶段或笑点阶段),然后根据这一点发送,例如引入变量LOCAL_JOKE_STATE
(0
最初,1
,如果你问“谁在那里?”和2
如果你问“XXXX谁?”)你的客户对特定笑话的反应是硬编码的,而不是对任何线索的反应。这通常是一个坏主意,在这种情况下会打破客户机-服务器通信的界限——这就像一次对话,其中一方按照预设的顺序回答了所问的任何问题,导致回答混乱、无序,但这可能是一致的,例如:
同样地,look at the example,那里没有硬编码的字符串数组
将
FixedMessageSequenceProtocol
对象设置为从1
开始。在Java中,数组是零索引的——因此服务器永远不会给出“告诉”这个turnip
笑话的线索。当然,从列表中的其他地方开始讲笑话是完全可以的。从你的问题来看,我想也许这就是你想要定制的产品总而言之,这段代码中有一些非常基本的错误,它试图执行(合理地)复杂的任务。我建议你试着从你链接的网站上获得一个代码的精确副本,然后逐步地一次改变一件事,直到它达到你想要的效果,或者你遇到了一个小而具体的问题,你可以问一个问题
如果你想做的主要定制是让协议有一个起点——只要改变一下就可以了——这很好。剩下的都没变,应该还能用