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

Author: Coffee, 2015-09-27

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:

  1. 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 1000milliseconde 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 ligne

    while ((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 process fromServer (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 variable LOCAL_JOKE_STATE (0 au départ, 1 si vous avez demandé " qui est là?"et 2 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;
    }
    
  2. 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.

  3. 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" la turnip 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.

 3
Author: J Richard Snape, 2015-10-06 14:39:37