Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java OutputStream only flushes data on close

Socket socket = new Socket("192.168.178.47", 82);

OutputStream out = socket.getOutputStream();
out.write("{ \"phone\": \"23456789\" }".getBytes());
out.flush();

//Server

InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();

int i = 0;
while((i = in.read()) >= 0) {
    bOut.write(i);
}

String complete = new String(bOut.toByteArray(), "UTF-8");

I had tried to send data via OutputStream to a socket but the data is not flushing. If I add an out.close(); to the end then it works perfectly, but the socket is closed and I cannot accept the response. Does anybody know why? The server is not giving any type of error. I had used Java 1.7!

like image 805
Neatoro Avatar asked Apr 20 '15 14:04

Neatoro


People also ask

When should I flush the output stream in Java?

It should be flushed when the stream is closed. This should happen when the program exits or when you explicitly invoke the close () method: For example, again assuming out is an OutputStream of some sort, calling out.close () closes the stream and implicitly flushes it.

What happens if output stream is not closed in Java?

If close () method of input stream will throw an Exception then output stream will not be closed, i.e. fos.close () will not even execute if fis.close () throws exception. This means the file descriptor held by OutputStream will never release causing a resource leak in the Java program.

What does the flush () method of OutputStream class do?

The flush () method of OutputStream class is used to flush the content of the buffer to the output stream. A buffer is a portion in memory that is used to store a stream of data (characters). That data sometimes will only get sent to an output device, when the buffer is full. The flush method of OutputStream does nothing.

What are the methods of OutputStream in Java?

Methods of OutputStream. 1 write () - writes the specified byte to the output stream. 2 write (byte [] array) - writes the bytes from the specified array to the output stream. 3 flush () - forces to write all data present in output stream to the destination. 4 close () - closes the output stream.


2 Answers

It is possible that the server is waiting for the end of line. If this is the case add "\n" to the text

like image 180
Evgeniy Dorofeev Avatar answered Sep 23 '22 05:09

Evgeniy Dorofeev


I'm not sure of the labelling "//Server" in your question, but I'm assuming the following code is the server code:

InputStream in = client.getInputStream();
ByteArrayOutputStream bOut = new ByteArrayOutputStream();

int i = 0;
while((i = in.read()) >= 0) {
    bOut.write(i);
}

String complete = new String(bOut.toByteArray(), "UTF-8");

This will continue to read, blocking each time, until it gets a value from read() less than zero. That only happens if the stream is closed.

It really looks like you need to establish your own protocol. So instead of looking for "<=0" look for some constant value that signals the end of the message.

Here's a quick demonstration of what I mean (I didn't have time yesterday). I have 3 classes, Message,MyClient (which also is the main class), and MyServer. Notice there isn't anything about sending or receiving a newline. Nothing is setting tcpNoDelay. But it works fine. Some other notes:

  • This code only sends and receives a single request and response.
  • It doesn't support sending multiple Message instances. That would require checking for the start of a Message as well as the end.

Message class:

public class Message {
    public static final String MSG_START = "<message>";
    public static final String MSG_END = "</message>";

    private final String content;

    public Message(String string){
        content = string;
    }

    @Override
    public String toString(){
        return MSG_START + content + MSG_END;
    }
}

MyServer class

public class MyServer implements Runnable{
    public static final int PORT = 55555;

    @Override
    public void run(){
        try {
            ServerSocket serverSocket = new ServerSocket(PORT);
            Socket socket = serverSocket.accept();
            String message = getMessage(socket);
            System.out.println("Server got the message:  " + message);
            sendResponse(socket);
        }catch (IOException e){
            throw new IllegalStateException(e);
        }
    }

    private void sendResponse(Socket socket) throws IOException{
        Message message = new Message("Ack");
        System.out.println("Server now sending a response to the client: " + message);
        OutputStream out = socket.getOutputStream();
        out.write(message.toString().getBytes("UTF-8"));
    }

    private String getMessage(Socket socket) throws IOException{

        BufferedInputStream in = new BufferedInputStream(socket.getInputStream());
        StringBuilder sb = new StringBuilder(100);
        byte[] bytes = new byte[1024<<8];
        while(sb.lastIndexOf(Message.MSG_END) == -1){
            int bytesRead = in.read(bytes);
            sb.append(new String(bytes,0,bytesRead,"UTF-8"));
        }

        return sb.toString();
    }
}

MyClient class

public class MyClient {

    public static void main(String[] args){
        MyClient client = new MyClient();

        Thread server = new Thread(new MyServer());
        server.start();

        client.performCall();
    }

    public void performCall(){
        try {
            Socket socket = new Socket("127.0.0.1",MyServer.PORT);
            sendMessage(socket, "Why hello there!");
            System.out.println("Client got a response from the server: " + getResponse(socket));
        } catch (IOException e) {
            throw new IllegalStateException(e);
        }
    }

    public String getResponse(Socket socket) throws IOException{
        String response;

        StringBuilder sb = new StringBuilder(100);
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        while(sb.lastIndexOf(Message.MSG_END) == -1){
            int bytesRead = in.read(bytes);
            sb.append(new String(bytes,0,bytesRead,"UTF-8"));
        }
        response = sb.toString();

        return response;
    }

    public void sendMessage(Socket socket, String message) throws IOException{
        Message msg = new Message(message);
        System.out.println("Client now sending message to server: " + msg);
        OutputStream out = socket.getOutputStream();
        out.write(msg.toString().getBytes("UTF-8"));
    }
}

The output

Client now sending message to server: Why hello there!
Server got the message:  Why hello there!
Server now sending a response to the client: Ack
Client got a response from the server: Ack

Process finished with exit code 0
like image 22
MadConan Avatar answered Sep 23 '22 05:09

MadConan