Roy Hinkley
Roy Hinkley

Reputation: 10651

DataInputStream hangs on read

I have a socket client that hangs whenever I try to read the input stream from the socket.

DataInputStream dis = new DataInputStream(socket.getInputStream());

int singleByte;
while((singleByte = dis.read()) != -1) {  //<-- hangs here
    char c = (char)singleByte;                     
    // append character
    message_string += c;                        
}

I have confirmed that the server is echoing back what I send it in raw ASCII.

What am I not understanding? Why is it hanging when trying to read the server response?

Server side (handles the request):

class HandleInputBuffer implements Runnable {

    private String msg = "";
    private String response = "8"; 

    public HandleInputBuffer(String str) {
        this.msg = str;
    }

    @Override
    public void run() {

        String exception_msg = "";

        // process incoming message
        try {
            if(msg!=null){
                if(msg.length()>0){

                    // create and send reply
                    String response = "8"; 

                    // ****************************
                    // create and send response
                    // ****************************
                    try {

                        response = msg;
                        output_stream = new DataOutputStream(client_socket.getOutputStream());
                        output_stream.writeInt(response.getBytes("US-ASCII").length);
                        output_stream.write(response.getBytes("US-ASCII")); 
                        output_stream.flush();                          
                        output_stream.close();

                        //client_socket.shutdownOutput();
                        client_socket.close();


                    } catch (IOException e) {
                        e.printStackTrace();
                        try{output_stream.flush();} catch (IOException e1) {}
                        try {client_socket.close();} catch (IOException e1) {}
                        try {updateConversationHandler = new Handler();} catch (Exception e1) {}

                        return;
                    } 

                }

            }
        } catch (Exception e) {             
            e.printStackTrace();                
        }

    }

}

Client side refactor - This code hangs int length = dis.readInt();

InetAddress serverAddr = InetAddress.getByName(edit_ip_address.getText().toString());

if(socket == null){         
     socket = new Socket(serverAddr, Integer.parseInt(edit_port.getText().toString()));         
}

// send bytes
output_stream = new DataOutputStream(socket.getOutputStream());                        
output_stream.write(command.getBytes("US-ASCII"));

DataInputStream dis = new DataInputStream(socket.getInputStream());

int length = dis.readInt();
byte[] buffer = new byte[length];  //<-- OutOfMemoryException
dis.readFully(buffer);
for (byte b:buffer){
     char c = (char)b;  
     message_string += c;
}

Upvotes: 1

Views: 3667

Answers (1)

user207421
user207421

Reputation: 311054

This loop will block until the peer closes the connection.

Ergo the peer is not closing the connection.

EDIT The correct way to read what you're sending is as follows:

You need to read the integer length word that you're writing. It doesn't magically appear via available():

int length = dis.readInt();
byte[] buffer = new byte[length];
dis.readFully(buffer);

But I would throw the sending and receiving code away and use readUTF()/writeUTF(), assuming the data is character data. If it isn't, you shouldn't be assembling it as a String.

EDIT 2 Proof that this works:

Client.java:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;

public class Client
{
    public static void  main(String[] args) throws IOException
    {
        try (Socket s = new Socket("localhost", 9999))
        {
            DataOutputStream    out = new DataOutputStream(s.getOutputStream());
            out.writeInt(1);
            out.writeBytes("8");
            DataInputStream in = new DataInputStream(s.getInputStream());
            int count = in.readInt();
            System.out.println("Reading "+count+" bytes");
            byte[] buffer = new byte[count];
            in.readFully(buffer);
            System.out.write(buffer, 0, count);
            System.out.println();
        }
    }
}

Server.java:

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class Server
{
    public static void  main(String[] args) throws IOException
    {
        try (ServerSocket ss = new ServerSocket(9999))
        {
            try (Socket s = ss.accept())
            {
                DataInputStream in = new DataInputStream(s.getInputStream());
                int count = in.readInt();
                System.out.println("Reading "+count+" bytes");
                byte[] buffer = new byte[count];
                in.readFully(buffer);
                System.out.write(buffer, 0, count);
                System.out.println();
                DataOutputStream    out = new DataOutputStream(s.getOutputStream());
                out.writeInt(count);
                out.write(buffer, 0, count);
            }
        }
    }
}

If yours doesn't, you are reading something else from the socket, or writing something else to it, or not running the code you think you're running.

Upvotes: 2

Related Questions