2017-10-08 5 views
0

Juste pour être complètement transparent, ceci est pour une affectation.Buffered Reader pour une socket n'est jamais prêt

Il y a plus à faire, mais pour le moment je suis juste essayer d'obtenir ce qui suit:

  1. Noeud A lit depuis un fichier texte
  2. nœud A envoie un fichier texte (moins le premier ligne) pour le noeud B en utilisant une douille
  3. Node B lue à partir de ladite douille, et l'affiche sur la console à

Toutefois, dès maintenant, il semble que ce soit l'information est en cours d'envoi, ou ça ne se lit pas corre cte par le nœud B.

Dans ma classe principale, je mis en place les nœuds comme celui-ci:

NodeA nodeA = new NodeA(); 
NodeB nodeB = new NodeB(); 

new Thread(nodeA).start(); 
new Thread(nodeB).start(); 

Dans le nœud A, je fais ceci:

//Open a socket for talking with NodeB 
Socket mySocket = new Socket(InetAddress.getLocalHost(), portNum); 

//Set up the socket's output 
PrintWriter out = new PrintWriter(mySocket.getOutputStream(), true); 

//Loop through the lines of the confA file, writing them to the socket 
String line = bufferedReader.readLine(); 
while (line != null) 
{ 
    //Write the line to the socket, get the next line 
    out.println(line); //updated to println, this flushes and fixes another problem 
    out.flush(); 
    line = bufferedReader.readLine(); 
} 

//Close the socket 
mySocket.close(); 

Notez que les travaux de boucle de noeud A bien. Il ne boucle pas toujours et passe par les lignes de texte prévues lorsque j'ai testé avec des instructions d'impression.

Puis, sur la fin du noeud B: Mise à jour pour afficher du code actuel Node B

//Open the socket 
ServerSocket mySocket = new ServerSocket(portNum); 
Socket connectionSocket = mySocket.accept(); 

//Set up a reader on the socket to get what's coming from it 
BufferedReader in = new BufferedReader(new InputStreamReader(connectionSocket.getInputStream())); 

String line = in.readLine(); //hang occurs here 

while(line != null) { 
    System.out.println(line); 
    line = in.readLine();; 
} 

Cependant, in.ready() est jamais vrai. J'ai essayé d'attendre que cela se produise en utilisant une boucle while mais cela n'arrive jamais.

Je ne sais vraiment pas pourquoi. Je n'ai aucune idée si je configure correctement le socket, si j'installe le serveur correctement, si j'écoute correctement, etc.

Je viens de penser que faire B dans un serveur qui écoute A a fait le plus de sens . J'espère que c'est vrai. Cela ressemble à ce que j'ai vu d'autres exemples sur SO.

Merci pour toute l'aide. Je suis extrêmement familier avec les prises, les ports, l'écoute et d'autres, alors pardonnez-moi si je ne comprends pas vos suggestions au début. Je ferai de mon mieux pour le comprendre au fur et à mesure. Je me suis abstenu d'ajouter tout le code pour rendre le code plus lisible et plus clair, mais si vous avez besoin de plus d'informations n'hésitez pas à demander et je ferai de mon mieux pour vous le fournir.

+0

1) Chaque fois que 'ServerSocket.accept()' renvoie, une socket connectée est établie entre le serveur et le client. Pour * cette * connexion, vous ne devez pas appeler 'ServerSocket.accept()' à nouveau. 2) Dans votre client, PrintWriter tamponne les données en interne. Si vous voulez que le résultat de l'appel 'out.print (line);' soit immédiatement visible sur le réseau, vous devez appeler 'out.flush()' comme instruction suivante. –

+0

Tout 'ready()' est retourné si la lecture suivante retournera immédiatement. Voir [la documentation] (https://docs.oracle.com/javase/9/docs/api/java/io/Reader.html#ready--). – VGR

Répondre

2

Le serveur doit d'abord obtenir de la socket serveur le socket vers le client.

connectionSocket = mySocket.accept(); 

Le thread du serveur sera mis en veille jusqu'à ce qu'un client l'accepte comme connectionSocket.

Puis vous pouvez lire depuis la connectionSocket. ready n'étant pas nécessaire.

Comme il s'agit d'une affectation, je vous laisse le reste.


Par la façon dont un serveur typique faire:

for (;;) { 
    Socket socket = serverSocket.accept(); 
    ... pass the socket to a thread from a pool of threads 
} 
+0

Merci pour la réponse, mais certaines choses sont encore très confuses à ce sujet. Une fois que le serveur a fini d'attendre et que le client s'est connecté, je n'aurais pas besoin de faire un autre .accept(), n'est-ce pas? J'ai essayé de changer mon code pour avoir seulement le .accept initial, mais je n'arrive toujours pas à lire depuis le socket, il se bloque sur readLine() pour toujours. –

+1

Vous ne devez avoir qu'un seul objet ServerSocket.accept qui fournit un socket à lire. –

+0

Merci. J'ai mis à jour le code avec la suppression du .accepts() supplémentaire et la suppression du .ready() et maintenant montrer où le blocage se produit. –

1

Je pense que le problème est que prêt signifie simplement que si vous appelez une lecture, il ne bloquera pas. Vous pouvez voir le code qui est exécuté si vous regardez la fonction sur grepcode:

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7u40-b43/java/io/BufferedReader.java#BufferedReader.ready%28%29

Un fil prêt signifie juste qu'il ne va pas bloquer, ce qui est utile lorsque vous voulez vous assurer que votre fil n » Je ne vais pas vous dire si vous avez un tampon ou non. Ce que vous voulez faire est d'effectuer la readline, comme un appel de blocage, jusqu'à ce que les données sont consommées. Si vous ne voulez pas que cela bloque votre thread actuel, alors essayez un nouveau thread consommateur spécifique pour cette lecture qui peut bloquer. En outre, assurez-vous que vous terminez votre communication d'envoi avec une socket fermée ou vider pour indiquer au flux consommateur lorsqu'il est terminé. Et vous avez seulement besoin de socket accepter une fois par session ouverte/fermée.

+0

Cela ne me dérange pas que la lecture bloque mon fil de discussion actuel, cela ne devrait pas poser de problème du tout. J'ai essayé de changer mon code pour n'avoir qu'un seul .accept() initialement et changer in.ready() pour juste m'assurer que la ligne retournée par readLine() n'est pas nulle (il y a plus de lignes à déplacer pour lire) mais il est toujours suspendu à la readLine() initiale que j'essaie de faire. –

+0

Readline nécessite la fin de la chaîne, elle recherche une socket EOL ou fermée. Si cela se bloque, cela signifie qu'il attend plus de données. Vous pouvez fermer la prise sur l'écrivain à la fin de l'écriture comme un test pour confirmer. – user1442498

+0

Merci. J'ai testé en mettant un mySocket.close(); à la fin du code du nœud A. Pas de chance cependant. Aurais-je besoin de le fermer à l'autre extrémité aussi? –