Aiden Strydom
Aiden Strydom

Reputation: 1208

BufferedWriter does not flush

I have the following problem....

            try 
            {
                clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()));

                while(true)
                { 
                    String clientRequest = "";
                    String tempStr = clientInput.readLine();

                    while(tempStr != null && !tempStr.equals("null"))
                    {
                        System.out.println(tempStr);
                        clientRequest += tempStr + " ";
                        tempStr = clientInput.readLine();
                    }

                    //Parse Request
                    ArrayList<String> tokenArray = parseRequest(clientRequest);

                    Calendar c = Calendar.getInstance();

                    switch(tokenArray.get(0))
                    {
                        case "GET": 
                        {
                            clientOutput.write("HTTP/1.1 200 OK\r\n");
                            clientOutput.write("Date: " + c.getDisplayName(0, Calendar.LONG, Locale.UK).toString() + "\r\n");
                            clientOutput.write("Server: Java HTTP Server v1.0\r\n");
                            clientOutput.flush();
                            break;
                            //Write File
                        }
                        default: 
                        {
                            clientOutput.write("500\r\n");
                            clientOutput.flush();
                        }
                    }
                } 
            }

Every thing works completely fine up-and-till the clientOutput.write("HTTP....... line, the client just keeps waiting and waiting... i've attempted to flush after every sucsessive write and yet nothing..... BUT This is the weird part - if i write to and flush before the code enters the while-loop the the writes in the case "GET": works perfectly...... ie

The code does execute all the way to the

                            clientOutput.flush();
                            break;
                            //Write File

.

              try 
             {
                clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()));

                clientOutput.write("HTTP/1.1 200 OK\r\n");
                clientOutput.flush();

                while(true)
                { 
                    String clientRequest = "";
                    String tempStr = clientInput.readLine();

                    while(tempStr != null && !tempStr.equals("null"))
                    {
                        System.out.println(tempStr);
                        clientRequest += tempStr + " ";
                        tempStr = clientInput.readLine();
                    }

                    //Parse Request
                    ArrayList<String> tokenArray = parseRequest(clientRequest);

                    Calendar c = Calendar.getInstance();

                    switch(tokenArray.get(0))
                    {
                        case "GET": 
                        {
                            clientOutput.write("HTTP/1.1 200 OK\r\n");
                            clientOutput.write("Date: " + c.getDisplayName(0, Calendar.LONG, Locale.UK).toString() + "\r\n");
                            clientOutput.write("Server: Java HTTP Server v1.0\r\n");
                            clientOutput.flush();
                            break;
                            //Write File
                        }

Here is the code for the client

        Socket s = new Socket("localhost", 1337);

        BufferedReader fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter toServer = new BufferedWriter(new PrintWriter(s.getOutputStream()));

        toServer.write("GET index.html HTTP/1.1\r\n");
        toServer.write("HOST: 127.0.0.1\r\n");
        toServer.write("Connection: close\r\n");
        toServer.write("\r\n");
        toServer.write("null\r\n");
        toServer.flush();   

        while(true)
        {
            String ss = fromServer.readLine();
            if(ss != null && !ss.equals("null"))
                System.out.println(ss);
        }

Server Class: Strydom_A_201103578_P03

public class Strydom_A_201103578_P03
{
    Thread[] threadArray = new Thread[5];
    int ClientCount = 0;

    public Strydom_A_201103578_P03() throws ClientSizeExceededException 
    {
        ServerSocket httpServer = null;
    try 
    {
        httpServer = new ServerSocket(1337);
    } 
    catch (IOException ex) 
    {
        Logger.getLogger(Strydom_A_201103578_P03.class.getName()).log(Level.SEVERE, null, ex);
    }

    while(true)
    {
        try
        {
            //Wait for connection

            Socket clientSocket = httpServer.accept();

            if(ClientCount < 5)
            {
                threadArray[ClientCount] = new Thread(new clientHandler(clientSocket));
                threadArray[ClientCount].start();
                ClientCount++;
            }
            else
            {
                throw new ClientSizeExceededException();
            }

        }
        catch(IOException ex)
        {

        }
        finally
        {

        }
    }
}

class clientHandler implements Runnable
{
    Socket clientSocket;
    public clientHandler(Socket clientSocket) 
    {
        this.clientSocket = clientSocket;
    }

    @Override
    public void run() 
    {
        BufferedReader clientInput = null;
        BufferedWriter clientOutput = null;

            try 
            {
                clientInput = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
                clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream()));

                clientOutput.write(" ");
                clientOutput.flush();

                while(true)
                { 
                    String clientRequest = "";
                    String tempStr = clientInput.readLine();

                    while(tempStr != null && !tempStr.equals("null"))
                    {
                        System.out.println(tempStr);
                        clientRequest += tempStr + " ";
                        tempStr = clientInput.readLine();
                    }

                    //Parse Request
                    ArrayList<String> tokenArray = parseRequest(clientRequest);

                    Calendar c = Calendar.getInstance();

                    switch(tokenArray.get(0))
                    {
                        case "GET": 
                        {
                            clientOutput.write("HTTP/1.1 200 OK\r\n");
                            clientOutput.write("Date: " + c.getDisplayName(0, Calendar.LONG, Locale.UK).toString() + "\r\n");
                            clientOutput.write("Server: Java HTTP Server v1.0\r\n");
                            clientOutput.flush();
                            break;
                            //Write File
                        }
                        default: 
                        {
                            clientOutput.write("500\r\n");
                            clientOutput.flush();
                        }
                    }
                } 
            }
            catch (IOException ex) 
            {
                Logger.getLogger(Strydom_A_201103578_P03.class.getName()).log(Level.SEVERE, null, ex);
            } 
            finally 
            {
                try 
                {
                    clientInput.close();
                    clientOutput.close();
                } 
                catch (IOException ex) 
                {
                    Logger.getLogger(Strydom_A_201103578_P03.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
    }

    private ArrayList<String> parseRequest(String tempStr) 
    {
        StringTokenizer httpTokens = new StringTokenizer(tempStr, " ");
        ArrayList<String> tokens = new ArrayList<>();

        while(httpTokens.hasMoreTokens())
            tokens.add(httpTokens.nextToken());

        return tokens;
    }
}


public static void main(String[] args) throws ClientSizeExceededException 
{
    new Strydom_A_201103578_P03();
}

}

public class TestClient 
{

public TestClient() 
{
    try 
    {
        Socket s = new Socket("localhost", 1337);

        BufferedReader fromServer = new BufferedReader(new InputStreamReader(s.getInputStream()));
        BufferedWriter toServer = new BufferedWriter(new PrintWriter(s.getOutputStream()));

        toServer.write("GET index.html HTTP/1.1\r\n");
        toServer.write("HOST: 127.0.0.1\r\n");
        toServer.write("Connection: close\r\n");
        toServer.write("\r\n");
        toServer.write("null\r\n");
        toServer.flush();   

        while(true)
        {
            String ss = fromServer.readLine();
            if(ss != null && !ss.equals("null"))
                System.out.println(ss);
        }

    } 
    catch (UnknownHostException ex) 
    {
        Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
    } 
    catch (IOException ex) 
    {
        Logger.getLogger(TestClient.class.getName()).log(Level.SEVERE, null, ex);
    }

}



public static void main(String[] args) 
{
    new TestClient();
}

}

Client Class: TestClient

Create a project( or 2) and run the files

Upvotes: 1

Views: 3832

Answers (4)

user207421
user207421

Reputation: 310884

The problem here is the PrintWriter. It swallows exceptions. Change it to an OutputStreamWriter. Then you will see any exception that is being swallowed. In general you should avoid PrintWriters and PrintOutputStreams over a network. They swallow exceptions that you need to know about.

Upvotes: 2

Aiden Strydom
Aiden Strydom

Reputation: 1208

So for the futhering of my now ended suffering - here is what i finally did....

I changed both the server and the clients readers from BufferedReader/Writer to DataInputstream/OutputStream.... And it works perfectly now - ! Thanks to everyone

Aiden

Upvotes: 0

Jon Lin
Jon Lin

Reputation: 143876

You need to change your inner while loop to look for the end of the client's request:

while(tempStr != null && !tempStr.equals("null"))

to:

while(tempStr != null && !tempStr.equals("null") && !tempStr.equals(""))

The client won't disconnect (causing a null) after it sends a request. It will give you a blank line to indicate the end of its request.

Reason why returning the response header right away is working? Maybe the client just reads the 200 and (eventually) disconnects? So when you are reading the client's request, it ends and you get a null eventually.


EDIT:

So running your code, it works fine for me. Both the client and server are sending and receiving both requests and responses. However, the server never disconnects (the client includes a Connection: close header) and the client continues to block on readLine(). Unsurprisinly, when I include the write() and flush() immediately after setting up the connection on the server-side nothing changes except I see HTTP/1.1 200 OK twice on the client's end. Maybe all you need to do is close the clientSocket in a finally{} block at the end of your try/catch{}?

Upvotes: 0

Kumar Vivek Mitra
Kumar Vivek Mitra

Reputation: 33534

Just do this and it will work..........

Add true as the 2nd parameter in the PrintWriter

clientOutput = new BufferedWriter(new PrintWriter(clientSocket.getOutputStream(), true));

Upvotes: -1

Related Questions