Pourquoi mes blagues KnockKnock sont-elles hors service ici (code réseau Java)?
Je fais un projet où j'ai modifié l'exemple de code de réseau Java d'Oracle, qui est une application de blague Knock-Knock en réseau.
Je veux le faire fonctionner par lui-même. Voici mon code pour le KnockKnockServer modifié:
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();
}
}
Et ce qui suit est mon côté client :
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);
}
}
Enfin, j'ai légèrement modifié le protocole.classe java (lien ici à Pastebin ) pour pouvoir prendre la position de la blague. Cette classe a juste un grand multiple-case if-then loop (presque comme une instruction de commutateur complexe), qui prend soin de la séquence de blague.
Mon problème est que lorsque j'exécute mon code, la commande est incorrecte. Voici à quoi cela ressemble lors de la sortie:
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!
Pour la version complète des classes, veuillez consulter les liens pastebin suivants :
FixedMessageSéquenceProtocol.java
FixedMessageSequenceServer.java
FixedMessageSequenceClient.java
Tous les conseils appréciés, merci
1 answers
Modifier
Votre code dans le post ne correspond pas le code de votre lien. Cela rend la question incroyablement difficile à répondre et trompeuse.
Cela signifie également que la raison de votre problème est simplement une faute de frappe - vous avez "Who's there"
dans votre code client au lieu de "Who's there?"
. Je laisse la réponse originale ci-dessous, car if contient de bonnes informations sur la raison pour laquelle mettre ces chaînes codées en dur dans votre client est une mauvaise idée. Votre code passe par KKJokes
comme je pensez que vous avez l'intention, mais il y a une faute de frappe dans KKJokes[12]
Séquence des événements:
Le client initialise avec startPosition
défini sur 3
- c'est-à-dire en commençant par le "Who's there?"
pour la blague de la petite vieille dans KKJokes
Le serveur initialise [] avec currentJoke
défini sur 1
c'est-à-dire la blague de la vieille dame
Notez que le client imprime tous les messages du serveur (S:
) dans stdout
que vous reproduisez en sortie dans l'OP.
Server: Knock knock
Client (1 sec later): Who's there ?
S: Little Old Lady
C (1 sec later): Little Old Lady who?
S: I didn't know you could yodel! Want another? (y/n)
C: y
S: Knock! Knock!
C: Who's there?
S: Doctor
C: Doctor who?
S: Is there an owl doctor? Want another? (y/n)
C: y
S: Knock! Knock!
C: Who's there?
S: Teacher
C: Teacher who?
S: Teacher who says do ur HW please Want another? (y/n)
C: y
S: Knock! Knock!
C: Who's there <------ TYPO HERE - NO QUESTION MARK !!! ---------
S: You're supposed to say "Who's there?"! Try again. Knock! Knock!
C: Dog who?
S: You're supposed to say "Who's there?"! Try again. Knock! Knock!
C: y
S: You're supposed to say "Who's there?"! Try again. Knock! Knock!
C: Who's there?
S: Dog
C: Firefighter who?
S: You're supposed to say "Dog who?"! Try again. Knock! Knock!
C: y
S: You're supposed to say "Who's there?"! Try again. Knock! Knock!
C: Who's There?
S: Dog
C: Zoologist who?
S: You're supposed to say "Dog who?"! Try again. Knock! Knock!
C: y
Réponse originale
La raison sous-jacente qui votre sortie est en panne car dans votre client, vous ne traitez pas ce que vous recevez sur son entrée. Ainsi, votre client continue indépendamment de ce que fait votre serveur. Parfois, les messages arrivent juste à frapper la séquence que le serveur attend, de sorte que vous obtenez une sortie qui semble presque correcte, mais les blagues dans le mauvais ordre.
Voici les principaux problèmes avec le code:
-
Lorsque le client reçoit un message du serveur, il l'imprime simplement (
fromServer
), il ne le traite pas et ne change rien en fonction de ce qu'il reçoit. Vous configurez un flux d'entrée client (qui, je suppose, devrait "écouter" les mots "knock knock")br = new BufferedReader( new InputStreamReader ( kkSocket.getInputStream() ));
Vous parcourez simplement vos réponses avec un délai de
1000
milliseconde suivi de l'attente de quel que soit le serveur qui envoie, puis vous envoyez la réponse suivante dans la liste. Le serveur répond à ceux-ci correctement, parfois, si la réponse se trouve être ce qu'il attend (par coïncidence), racontant la prochaine partie de la blague, vous disant parfois " Vous êtes censé dire Qui est Là?!". Si vous regardez les code pour le client dans l'exemple que vous liez - vous verrez qu'il a une lignewhile ((fromServer = in.readLine()) != null)
Qui est le client qui attend quelque chose du serveur (indice ou punchline). S'il reçoit
"bye"
, il termine le programme, sinon il envoie une entrée utilisateur. Si vous souhaitez envoyer des réponses automatisées au lieu de la saisie utilisateur, vous devez probablement avoir quelque chose d'équivalent dans votre code-par exemple processfromServer
(peut-être en combinaison avec un état qui vous indique à quel stade vous êtes dans la blague-par exemple au stade de l'indice ou au stade de la punchline), puis envoyer en fonction de cela, par exemple introduire une variableLOCAL_JOKE_STATE
(0
au départ,1
si vous avez demandé " qui est là?"et2
si vous avez demandé" XXXX Qui?")if (fromServer.equals("Bye.")) break; if (LOCAL_JOKE_STATE == 0) { out.println("Who's there?"); LOCAL_JOKE_STATE = 1; } else if (LOCAL_JOKE_STATE == 1) { out.println(fromServer + " who?"); LOCAL_JOKE_STATE = 2; } else { out.println("y"); // get another joke LOCAL_JOKE_STATE = 0; }
-
Votre client est intialisé avec des réponses codées en dur à des blagues particulières-plutôt que de répondre à quelque indice que ce soit. C'est généralement une mauvaise idée et brise le point de communication client-serveur dans ce cas - ce serait comme une conversation où une partie a répondu dans une séquence prédéfinie à la question qui a été posée, conduisant à des réponses confuses et hors séquence, mais cela peut coïncider par exemple
Q (serveur) : "aimez-vous la météo Britannique?"
A (client) : "Pommes"
Q (serveur) : "Comment trouvez-vous l'absence d'un bon d'été?"
A (client): "Parce qu'ils sont verts"
Q (serveur): " Que diriez-vous de la sensation des feuilles d'automne sous vos pieds?"
A (client) : "Le crunch est merveilleux"
Encore une fois, regardez l'exemple, il n'y a pas de tableaux de chaînes codés en dur.
Vous configurez votre
FixedMessageSequenceProtocol
objet pour commencer à1
. En Java, les tableaux sont indexés à zéro-le serveur ne donnera donc jamais le indice pour "dire" laturnip
blague. Bien sûr, c'est parfaitement bien de commencer les blagues ailleurs dans la liste. D'après votre question, je pense que c'est peut-être la personnalisation que vous essayez de faire?
Dans l'ensemble - il y a des erreurs assez fondamentales dans ce code, qui essaie d'effectuer une tâche (raisonnablement) sophistiquée. Je vous suggère d'essayer d'obtenir une réplique exacte du code du site que vous liez en travaillant puis de changer très progressivement une chose à un temps jusqu'à ce qu'il fasse ce que vous voulez, ou que vous rencontriez un petit problème spécifique sur lequel vous pouvez poser une question.
Si la personnalisation principale que vous voulez faire est que le protocole prenne un point de départ - changez simplement cela comme vous l'avez fait - c'est bien. Laissez le reste le même - tout devrait toujours fonctionner.