1

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;                        
}
  • Hangs on while((singleByte = dis.read()) != -1) {

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;
}
Roy Hinkley
  • 10,111
  • 21
  • 80
  • 120
  • @Kayaman Yes, the output stream is getting flushed immediately after write. – Roy Hinkley Jan 06 '16 at 18:13
  • um .... your example does not compile, [DataInputStream#read](https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#read(byte[])) requires a parameter – specializt Jan 06 '16 at 18:22
  • 1
    @specializt Um, no it doesn't: there are three overloads, with zero, one, and three parameters respectively. – user207421 Jan 06 '16 at 18:24
  • no, there is no overload with zero parameters. You should've clicked that linked instead of assuming things – specializt Jan 06 '16 at 18:25
  • 1
    @specializt - I have no issues with compiling. My code compiles fine - that's how I know it is hanging on read. I don't know what else to tell you. – Roy Hinkley Jan 06 '16 at 18:27
  • well thats undefined behaviour then. Zero parameters are not documented. That may be the cause of his problem -- deprecated API, i think ... just a shot in the dark. – specializt Jan 06 '16 at 18:28
  • 1
    @specializt Yes there is: check the methods inherited from `FilterInputStream.` You should have read your link instead of assuming things. No deprecated API either. – user207421 Jan 06 '16 at 18:29

1 Answers1

2

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.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Shouldn't the connection be closed by the client? – Roy Hinkley Jan 06 '16 at 18:15
  • I have no idea. You haven't mentioned or described your protocol. If you don't want the peer to have to close the connection, don't read to end of stream. – user207421 Jan 06 '16 at 18:19
  • Closing socket at server makes no difference. It still hangs. – Roy Hinkley Jan 06 '16 at 18:30
  • That is simply not possible. Try again. – user207421 Jan 06 '16 at 18:31
  • Please see my edits - with server side code in place, I get the exact same behavior on the client side. – Roy Hinkley Jan 06 '16 at 18:33
  • See my edit above. Part of it relates to your recently deleted question about `available().` You don't need to flush a `DataOutputStream` unless there is an underlying `BufferedOutputStream,` and `flush()` before `close()` is redundant anyway. – user207421 Jan 06 '16 at 18:35
  • Then the response is zero length, or you've got out of sync somewhere else between the server and the client. – user207421 Jan 06 '16 at 18:38
  • I'm not sure how that would be - in the same thread: I open socket, write output stream then read input stream, or at least try - data is received at server, server echoes input with aforementioned code confirmed. – Roy Hinkley Jan 06 '16 at 18:42
  • My disconnect is between the `server response and client`. The server does get the client data and echoes it back to client. – Roy Hinkley Jan 06 '16 at 18:43
  • So you're *sending* a zero length request and the server is echoing it. You can see for yourself that this receiving code is symmetrical with the sending code, unlike everything else you've tried. – user207421 Jan 06 '16 at 18:43
  • No, I am sending single ASCII characters 0-8, as I choose. I know the server gets them, because it displays the particular character I sent on screen. I can see it. – Roy Hinkley Jan 06 '16 at 18:44
  • So something is not as you have represented here. Serialization uses code similar to this. It does work. How are you sending and receiving the request? – user207421 Jan 06 '16 at 18:45
  • Please see my client side refactor - hangs (blocked) at `int length = dis.readInt();` – Roy Hinkley Jan 06 '16 at 18:55
  • Please answer my question about the request. Edit that code into your question. Are you doing anything else with the socket? Any `BufferedInput/OutputStreams` anywhere? And I cannot reconcile '`dis.readInt()` always returns 0' with 'hangs (blocked) at `int length = dis.readInt()`'. Which is it? – user207421 Jan 06 '16 at 18:57
  • The client side code refactor is literally how it is in the method. – Roy Hinkley Jan 06 '16 at 19:05
  • That's the response code. I asked how the *request* is being sent and received. You haven't explained about returning zero *versus* blocking either. It's mpossible to help you if you won't answer the questions you're asked here. – user207421 Jan 07 '16 at 00:25
  • I don't know what you mean, the code is as I have presented here (mutated). When you plug your code into my client software and hit another server that returns 10 packets of integer values, it raises and outofmemoryexception on `byte[] buffer = new byte[length];` I don't know what to tell you. – Roy Hinkley Jan 07 '16 at 00:38
  • BTW, I am trying to answer your questions - but I don't find them clear. – Roy Hinkley Jan 07 '16 at 00:41
  • The code you have posted sends and receives a response. I am asking you, for the third time, what the code that sends and receives the request looks like. You have stated that `readInt()` both returns zero and blocks, and you haven't clarified that when asked. You are now implying that it is returning a very large value: yet a third case. I've also asked you whether you're doing anything else with these sockets, and whether there are any buffered streams present anywhere, and you haven't answered that either. Please go through everything I've asked you here and answer it, point by point. – user207421 Jan 07 '16 at 00:51
  • NB There is nothing unclear about any of those questions, but if you found otherwise, you should have said so, instead of just ignoring them. – user207421 Jan 07 '16 at 00:57
  • I will post the full code for your inspection for both client and server. – Roy Hinkley Jan 07 '16 at 01:08
  • I have posted the relevant code for client and server. The server receives just fine, it's the reply that the issue is encountered. – Roy Hinkley Jan 07 '16 at 17:38
  • After four requests (I miscounted above) you have still haven't posted the code that receives the request. And you haven't clarified whether `readInt()` (a) blocks (b) returns zero or (c) returns a large number. I give up. You haven't provided code that exhibits the problem you describe. Question should be closed. – user207421 Jan 07 '16 at 22:41
  • I believe I have - The server side code (in the post) handles the request, and readInt() is (c) , specifically 837746688. So you confuse me. If that's not what you're looking for, what exactly do you mean be request? – Roy Hinkley Jan 07 '16 at 22:48
  • You are simply not reading what is written here. I said *'receive*' the request. The meaning of the word 'receive' is not the same as the meaning the word 'handle'. You need to provide a short complete example, including the connect code and all the I/O code, that exhibits the problem you are describing. Surely this is obvious! And you **STILL** haven't clarified about `readInt()`: you made three mutually contradictory claims about it and you haven't explained why you made them. – user207421 Jan 07 '16 at 23:15
  • I'm sorry, I have not meant to upset you - really. I have resolved the issue, which I would be happy to share in a pm. I will gladly delete this post if you delete your answer - I can't delete post with an answer. – Roy Hinkley Jan 08 '16 at 00:53
  • I have no intention of deleting my correct answer. You should post your solution here. Personal remarks are out of place. – user207421 Jan 08 '16 at 01:16