Search code examples
javaserversocket

while loop only stops at first loop then continues to run indefinitely


The goal of this practice program is simply to allow the client to continuously send strings of messages that the user inputs via typing and hitting enter key and prints it to console. The first time around , String messageFromClient = in.readLine(); in Server.java seems to block (Debugger won't let me step out). However after sending it a message like "hello", it continuously runs without blocking anymore.

I've been searching this up for a couple of hours but I guess I'm just not looking at the right places for the solution.

This link Java InputStream blocking read is probably the closest thing I've found that might help me.

Client.java

import java.io.*;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.*;
import java.net.InetAddress;
import java.util.Scanner;

public class Client {
    static Socket connectionToServer;
    public static void main(String[] args) {
        try{
            connectionToServer = new Socket("192.168.1.66", 6969);
            InetAddress inetAddress = connectionToServer.getInetAddress();
            System.out.print(
                    "Connection successful" +
                    "Connected to " + inetAddress.getHostAddress() +
                    "at " + inetAddress.getHostName() + "\n"
            );

            while(true) {
                String input = System.console().readLine();
                OutputStreamWriter dOut = new OutputStreamWriter(connectionToServer.getOutputStream());
                dOut.write(input, 0, input.length());
                //dOut.flush();
                dOut.close();
            }

        } catch (IOException exception){
            System.out.print("Failed to create socket");
        }

    }
}

Server.java

import java.io.*;
import java.net.*;

public class Server {
    public static void main(String[] args) {
        ServerSocket serverSocket;
        try {
            serverSocket = new ServerSocket(6969);
            System.out.print("Server is up and running \n");
        } catch (IOException exception){
            serverSocket = null;
            System.out.print("Cannot create ServerSocket");
        }

        while (true){
            try {
                System.out.print("Waiting from client.");
                Socket socket = serverSocket.accept();
                Thread newClientSocket = new Thread(new ServerThread(socket));
                newClientSocket.start();
                System.out.print("New thread created");
            } catch (IOException exception){
                System.out.print("Failed to create socket");
            }
        }
    }
}
////////////////////////////////////////////////////////////
class ServerThread implements Runnable{
    private Socket socket;
    //constructor
    ServerThread(Socket socket){
        System.out.print("I am a new thread");
        this.socket = socket;
    }

    public void run(){
        while(true){
            try{
                System.out.print("Waiting for input.");
                InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
                BufferedReader in = new BufferedReader(inputStreamReader);
                String messageFromClient = in.readLine();
                System.out.print(messageFromClient);
            } catch (IOException exception) {
                System.out.print(exception);
                break;
            }
        }
    }
}

Solution

  • You shouldn't construct a new BufferedReader for each loop iteration, since a BufferedReader will try to fill its buffer completely and possibly read beyond the end of the first line - and that data will be lost, since you're constructing a new BufferedReader after reading only the first line from it.

    Move the construction of the BufferedReader out of the loop, that should help you. Also, make sure that you close the socket when you're done with it.

    public void run() {
        try {
            try {
                InputStreamReader inputStreamReader = new InputStreamReader(socket.getInputStream());
                BufferedReader in = new BufferedReader(inputStreamReader);
                while (true) {
                    System.out.print("Waiting for input.");
                    String messageFromClient = in.readLine();
                    System.out.print(messageFromClient);
                }
            } finally {
                socket.close();
            }
        } catch (IOException exception) {
            System.out.print(exception);
            // TODO: handle exception
        }
    }
    

    On the sending side, you shouldn't close the socket's OutputStream for every line, because once you close it, you can't use it anymore. And you should send a newline to the server after the string, as the Console.readLine() method doesn't include it in its return value.

            OutputStreamWriter dOut = new OutputStreamWriter(connectionToServer.getOutputStream());
            while(true) {
                String input = System.console().readLine() + "\n";
                dOut.write(input, 0, input.length());
            }
            dOut.close();