2017-10-08 4 views
0

Um ganz transparent zu sein, ist dies für eine Aufgabe.Gepufferte Reader für einen Sockel ist nie fertig

Es gibt mehr zu tun, aber im Moment versuche ich nur folgendes zu erhalten:

  1. Knoten A liest aus einer Textdatei
  2. Knoten Eine Textdatei (minus der erste sendet Linie) unter Verwendung eines B-Buchse
  3. Knoten B an, die aus dem Sockel, und druckt es aus an die Konsole

jedoch jetzt mit dem Knoten entweder scheint es, dass die Information nicht gesendet wird, oder es wird nicht korrekt gelesen ctly von Knoten B.

In meiner Hauptklasse, ich die Knoten wie folgt aufgebaut:

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

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

In Knoten A, mache ich das:

//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(); 

Beachten Sie, dass Knoten A-Schleife funktioniert fein. Es wird nicht für immer wiederholt und durchläuft die beabsichtigten Textzeilen, wenn ich mit Druckanweisungen teste.

Dann, am Knoten B Ende: Aktualisiert aktuellen Knoten B Code

//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();; 
} 

jedoch in.ready() zu zeigen, ist nie wahr. Ich habe versucht, darauf zu warten, dass dies mit einer while-Schleife passiert, aber es kommt nie vor.

Ich bin mir wirklich nicht sicher warum. Ich habe keine Ahnung, ob ich den Socket korrekt eingerichtet habe, ob ich den Server korrekt eingerichtet habe, ob ich richtig zuhöre usw.

Ich dachte nur, dass es am sinnvollsten ist, B zu einem Server zu machen, der auf A hört . Ich hoffe, das stimmt. Es sieht ähnlich aus wie einige andere Beispiele auf SO.

Vielen Dank für jede Hilfe. Ich bin extrem mit Sockets, Ports, zuhören und sonst nicht vertraut, also vergib mir, wenn ich deine Vorschläge zuerst nicht verstehe. Ich werde mein Bestes geben, um es zu verstehen, während ich gehe.

Ich habe davon Abstand genommen, den ganzen Code hinzuzufügen, um es hoffentlich lesbarer zu machen und klar zu machen, wo das Problem sein könnte, aber wenn Sie mehr Informationen brauchen, zögern Sie nicht zu fragen und ich werde mein Bestes geben.

+0

1) Jedes Mal, wenn 'ServerSocket.accept()' zurückkehrt, haben Sie einen verbundenen Socket zwischen Server und Client eingerichtet. Für * diese * Verbindung rufen Sie 'ServerSocket.accept()' nicht erneut auf. 2) In Ihrem Client puffert der PrintWriter Daten intern. Wenn das Ergebnis des Aufrufs von 'out.print (line);' sofort im Netzwerk angezeigt werden soll, müssen Sie 'out.flush() 'als nächste Anweisung aufrufen. –

+0

Alles 'ready()' gibt zurück, ob der nächste Lesevorgang sofort zurückkehrt. Siehe [die Dokumentation] (https://docs.oracle.com/javase/9/docs/api/java/io/Reader.html#ready--). – VGR

Antwort

2

Der Server muss zuerst vom Server Socket den Socket an den Client abrufen.

Der Server-Thread wird in den Ruhezustand versetzt, bis ein Client die connectionSocket akzeptiert.

Dann können Sie von der connectionSocket lesen. ready wird nicht benötigt.

Da dies eine Aufgabe ist, überlasse ich Ihnen den Rest.


Durch die Art und Weise ein typischer Server tun würde:

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

Vielen Dank für die Antwort, aber ein paar Dinge sind immer noch sehr verwirrend. Sobald der Server fertig gewartet hat und der Client eine Verbindung hergestellt hat, sollte ich keine weitere .accept() durchführen müssen, oder? Ich habe versucht, meinen Code so zu ändern, dass ich nur die ursprüngliche .accept-Datei habe, aber ich kann immer noch nicht in der Lage sein, aus dem Socket zu lesen, er bleibt für immer bei readLine() hängen. –

+1

Sie sollten nur einen 'ServerSocket.accept' haben, der einen Socket liefert, von dem gelesen werden kann. –

+0

Vielen Dank. Ich habe den Code mit dem Entfernen der zusätzlichen .accepts() und dem Entfernen der .ready() aktualisiert und zeige jetzt, wo der Hang auftritt. –

1

ich glaube, das Problem ist, dass bereit bedeutet nur, dass, wenn Sie eine Lese nennen, es wird nicht blockieren. Sie können den Code sehen, dass, wenn Sie die Funktion auf grepcode nachschlagen ausgeführt wird:

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

nur ein fertiger Faden bedeutet zu blockieren, es wird nicht, was nützlich ist, wenn Sie, dass Ihr Thread isn sicherstellen wollen‘ Es wird nicht gebunden, aber sagt dir nicht wirklich, ob du einen Puffer hast oder nicht.

Sie möchten die readline als blockierenden Aufruf ausführen, bis die Daten verbraucht sind. Wenn Sie nicht möchten, dass dies Ihren aktuellen Thread blockiert, erstellen Sie einen neuen Consumer-Thread, der für diesen Lesevorgang spezifisch ist und blockiert werden kann.

Stellen Sie außerdem sicher, dass Sie Ihre send-Kommunikation entweder mit einem geschlossenen Socket oder mit einem Flush beenden, um dem konsumierenden Datenstrom anzuzeigen, wenn dieser abgeschlossen ist. Und Sie müssen Socket nur einmal pro Sitzung öffnen/schließen.

+0

Es stört mich nicht, dass das Lesen meinen aktuellen Thread blockiert, das sollte überhaupt kein Problem sein. Ich habe versucht, meinen Code zu ändern, um nur ein einziges .accept() zu haben und in.ready() zu ändern, um nur sicherzustellen, dass die von readLine() zurückgegebene Zeile nicht null ist (es gibt mehr Zeilen zum Einlesen), aber Es hängt immer noch an der anfänglichen readLine() Ich versuche es zu tun. –

+0

Readline benötigt ein Ende der Zeichenfolge, es sucht nach einem \ n EOL oder geschlossenen Socket. Wenn es hängt, bedeutet es, dass es auf mehr Daten wartet. Sie können den Socket am Schreiber am Ende des Schreibens als Test zur Bestätigung schließen. – user1442498

+0

Danke. Ich testete mit einem mySocket.close(); am Ende des Knotens A-Code. Noch kein Glück. Würde ich es auch am anderen Ende schließen müssen? –